Browse Source

Added support for defining custom depth-stencil textures in the renderpath, and performing depth-only rendering passes. Readded support for readable HW depth format (on D3D9 it uses the INTZ hack.) Improved RenderPath & Graphics Lua bindings. Added -renderpath command line option to specify the renderpath file to use.

Lasse Öörni 11 years ago
parent
commit
6fc05e9373

+ 17 - 0
Bin/CoreData/RenderPaths/ForwardHWDepth.xml

@@ -0,0 +1,17 @@
+<renderpath>
+    <rendertarget name="depth" sizedivisor="1 1" format="hwdepth" />
+    <command type="clear" depth="1.0" output="depth" />
+    <command type="scenepass" pass="depth" output="depth" />
+    <command type="clear" color="fog" depthstencil="depth" />
+    <command type="scenepass" pass="base" vertexlights="true" metadata="base" depthstencil="depth" />
+    <command type="forwardlights" pass="light" depthstencil="depth" />
+    <command type="scenepass" pass="postopaque" depthstencil="depth" />
+    <command type="scenepass" pass="refract" depthstencil="depth">
+        <texture unit="environment" name="viewport" />
+    </command>
+    <command type="scenepass" pass="alpha" vertexlights="true" sort="backtofront" metadata="alpha" depthstencil="depth"  />
+    <command type="scenepass" pass="postalpha" sort="backtofront" depthstencil="depth" />
+    <command type="quad" vs="GreyScaleDepth" ps="GreyScaleDepth">
+        <texture unit="depth" name="depth" />
+    </command>
+</renderpath>

+ 5 - 0
Bin/CoreData/Shaders/GLSL/Samplers.glsl

@@ -53,4 +53,9 @@ float DecodeDepth(vec3 depth)
     const vec3 dotValues = vec3(1.0, 1.0 / 255.0, 1.0 / (255.0 * 255.0));
     const vec3 dotValues = vec3(1.0, 1.0 / 255.0, 1.0 / (255.0 * 255.0));
     return dot(depth, dotValues);
     return dot(depth, dotValues);
 }
 }
+
+float ReconstructDepth(float hwDepth)
+{
+    return dot(vec2(hwDepth, cDepthReconstruct.y / (hwDepth - cDepthReconstruct.x)), cDepthReconstruct.zw);
+}
 #endif
 #endif

+ 1 - 0
Bin/CoreData/Shaders/GLSL/Uniforms.glsl

@@ -43,6 +43,7 @@ uniform mat4 cZone;
 uniform vec3 cAmbientColor;
 uniform vec3 cAmbientColor;
 uniform vec3 cCameraPosPS;
 uniform vec3 cCameraPosPS;
 uniform float cDeltaTimePS;
 uniform float cDeltaTimePS;
+uniform vec4 cDepthReconstruct;
 uniform float cElapsedTimePS;
 uniform float cElapsedTimePS;
 uniform vec4 cFogParams;
 uniform vec4 cFogParams;
 uniform vec3 cFogColor;
 uniform vec3 cFogColor;

+ 5 - 0
Bin/CoreData/Shaders/HLSL/Samplers.hlsl

@@ -45,4 +45,9 @@ float3 DecodeNormal(float4 normalInput)
         return normalInput.rgb * 2.0 - 1.0;
         return normalInput.rgb * 2.0 - 1.0;
     #endif
     #endif
 }
 }
+
+float ReconstructDepth(float hwDepth)
+{
+    return dot(float2(hwDepth, cDepthReconstruct.y / (hwDepth - cDepthReconstruct.x)), cDepthReconstruct.zw);
+}
 #endif
 #endif

+ 1 - 0
Bin/CoreData/Shaders/HLSL/Uniforms.hlsl

@@ -33,6 +33,7 @@ uniform float4x4 cLightMatrices[4];
 uniform float3 cAmbientColor;
 uniform float3 cAmbientColor;
 uniform float3 cCameraPosPS;
 uniform float3 cCameraPosPS;
 uniform float cDeltaTimePS;
 uniform float cDeltaTimePS;
+uniform float4 cDepthReconstruct;
 uniform float cElapsedTimePS;
 uniform float cElapsedTimePS;
 uniform float4 cFogParams;
 uniform float4 cFogParams;
 uniform float3 cFogColor;
 uniform float3 cFogColor;

+ 1 - 0
Source/Tools/Urho3DPlayer/Urho3DPlayer.cpp

@@ -108,6 +108,7 @@ void Urho3DPlayer::Setup()
             "-portrait    Use portrait orientations (iOS only)\n"
             "-portrait    Use portrait orientations (iOS only)\n"
             "-prepass     Use light pre-pass rendering\n"
             "-prepass     Use light pre-pass rendering\n"
             "-deferred    Use deferred rendering\n"
             "-deferred    Use deferred rendering\n"
+            "-renderpath <name> Use the named renderpath from the RenderPaths resource directory\n"
             "-lqshadows   Use low-quality (1-sample) shadow filtering\n"
             "-lqshadows   Use low-quality (1-sample) shadow filtering\n"
             "-noshadows   Disable shadow rendering\n"
             "-noshadows   Disable shadow rendering\n"
             "-nolimit     Disable frame limiter\n"
             "-nolimit     Disable frame limiter\n"

+ 5 - 0
Source/Urho3D/Engine/Engine.cpp

@@ -738,6 +738,11 @@ VariantMap Engine::ParseParameters(const Vector<String>& arguments)
                 ret["RenderPath"] = "RenderPaths/Prepass.xml";
                 ret["RenderPath"] = "RenderPaths/Prepass.xml";
             else if (argument == "deferred")
             else if (argument == "deferred")
                 ret["RenderPath"] = "RenderPaths/Deferred.xml";
                 ret["RenderPath"] = "RenderPaths/Deferred.xml";
+            else if (argument == "renderpath" && !value.Empty())
+            {
+                ret["RenderPath"] = "RenderPaths/" + value;
+                ++i;
+            }
             else if (argument == "noshadows")
             else if (argument == "noshadows")
                 ret["Shadows"] = false;
                 ret["Shadows"] = false;
             else if (argument == "lqshadows")
             else if (argument == "lqshadows")

+ 15 - 3
Source/Urho3D/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -242,7 +242,7 @@ static HWND GetWindowHandle(SDL_Window* window)
     return sysInfo.info.win.window;
     return sysInfo.info.win.window;
 }
 }
 
 
-static unsigned depthStencilFormat = D3DFMT_D24S8;
+static unsigned readableDepthFormat = 0;
 
 
 Graphics::Graphics(Context* context) :
 Graphics::Graphics(Context* context) :
     Object(context),
     Object(context),
@@ -2429,7 +2429,12 @@ unsigned Graphics::GetLinearDepthFormat()
 
 
 unsigned Graphics::GetDepthStencilFormat()
 unsigned Graphics::GetDepthStencilFormat()
 {
 {
-    return depthStencilFormat;
+    return D3DFMT_D24S8;
+}
+
+unsigned Graphics::GetReadableDepthFormat()
+{
+    return readableDepthFormat;
 }
 }
 
 
 unsigned Graphics::GetFormat(const String& formatName)
 unsigned Graphics::GetFormat(const String& formatName)
@@ -2466,6 +2471,8 @@ unsigned Graphics::GetFormat(const String& formatName)
         return GetLinearDepthFormat();
         return GetLinearDepthFormat();
     if (nameLower == "d24s8")
     if (nameLower == "d24s8")
         return GetDepthStencilFormat();
         return GetDepthStencilFormat();
+    if (nameLower == "readabledepth" || nameLower == "hwdepth")
+        return GetReadableDepthFormat();
     
     
     return GetRGBFormat();
     return GetRGBFormat();
 }
 }
@@ -2609,7 +2616,7 @@ void Graphics::CheckFeatureSupport()
     hardwareShadowSupport_ = false;
     hardwareShadowSupport_ = false;
     streamOffsetSupport_ = false;
     streamOffsetSupport_ = false;
     hasSM3_ = false;
     hasSM3_ = false;
-    depthStencilFormat = D3DFMT_D24S8;
+    readableDepthFormat = 0;
     
     
     // Check hardware shadow map support: prefer NVIDIA style hardware depth compared shadow maps if available
     // Check hardware shadow map support: prefer NVIDIA style hardware depth compared shadow maps if available
     shadowMapFormat_ = D3DFMT_D16;
     shadowMapFormat_ = D3DFMT_D16;
@@ -2648,6 +2655,11 @@ void Graphics::CheckFeatureSupport()
             impl_->adapterIdentifier_.DriverVersion.QuadPart <= 0x0007000f000a05d0ULL)
             impl_->adapterIdentifier_.DriverVersion.QuadPart <= 0x0007000f000a05d0ULL)
             hardwareShadowSupport_ = false;
             hardwareShadowSupport_ = false;
     }
     }
+
+    // Check for readable depth (INTZ hack)
+    D3DFORMAT intZFormat = (D3DFORMAT)MAKEFOURCC('I', 'N', 'T', 'Z');
+    if (impl_->CheckFormatSupport(intZFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE))
+        readableDepthFormat = intZFormat;
     
     
     // Check for dummy color rendertarget format used with hardware shadow maps
     // Check for dummy color rendertarget format used with hardware shadow maps
     dummyColorFormat_ = D3DFMT_A8R8G8B8;
     dummyColorFormat_ = D3DFMT_A8R8G8B8;

+ 4 - 0
Source/Urho3D/Graphics/Direct3D9/D3D9Graphics.h

@@ -281,6 +281,8 @@ public:
     bool GetDeferredSupport() const { return deferredSupport_; }
     bool GetDeferredSupport() const { return deferredSupport_; }
     /// Return whether shadow map depth compare is done in hardware.
     /// Return whether shadow map depth compare is done in hardware.
     bool GetHardwareShadowSupport() const { return hardwareShadowSupport_; }
     bool GetHardwareShadowSupport() const { return hardwareShadowSupport_; }
+    /// Return whether a readable hardware depth format is available.
+    bool GetReadableDepthSupport() const { return GetReadableDepthFormat() != 0; }
     /// Return whether stream offset is supported.
     /// Return whether stream offset is supported.
     bool GetStreamOffsetSupport() const { return streamOffsetSupport_; }
     bool GetStreamOffsetSupport() const { return streamOffsetSupport_; }
     /// Return whether sRGB conversion on texture sampling is supported.
     /// Return whether sRGB conversion on texture sampling is supported.
@@ -421,6 +423,8 @@ public:
     static unsigned GetLinearDepthFormat();
     static unsigned GetLinearDepthFormat();
     /// Return the API-specific hardware depth-stencil texture format.
     /// Return the API-specific hardware depth-stencil texture format.
     static unsigned GetDepthStencilFormat();
     static unsigned GetDepthStencilFormat();
+    /// Return the API-specific readable hardware depth format, or 0 if not supported.
+    static unsigned GetReadableDepthFormat();
     /// Return the API-specific texture format from a textual description, for example "rgb".
     /// Return the API-specific texture format from a textual description, for example "rgb".
     static unsigned GetFormat(const String& formatName);
     static unsigned GetFormat(const String& formatName);
     
     

+ 1 - 0
Source/Urho3D/Graphics/GraphicsDefs.cpp

@@ -54,6 +54,7 @@ StringHash VSP_VERTEXLIGHTS("VertexLights");
 StringHash PSP_AMBIENTCOLOR("AmbientColor");
 StringHash PSP_AMBIENTCOLOR("AmbientColor");
 StringHash PSP_CAMERAPOS("CameraPosPS");
 StringHash PSP_CAMERAPOS("CameraPosPS");
 StringHash PSP_DELTATIME("DeltaTimePS");
 StringHash PSP_DELTATIME("DeltaTimePS");
+StringHash PSP_DEPTHRECONSTRUCT("DepthReconstruct");
 StringHash PSP_ELAPSEDTIME("ElapsedTimePS");
 StringHash PSP_ELAPSEDTIME("ElapsedTimePS");
 StringHash PSP_FOGCOLOR("FogColor");
 StringHash PSP_FOGCOLOR("FogColor");
 StringHash PSP_FOGPARAMS("FogParams");
 StringHash PSP_FOGPARAMS("FogParams");

+ 1 - 0
Source/Urho3D/Graphics/GraphicsDefs.h

@@ -285,6 +285,7 @@ extern StringHash VSP_VERTEXLIGHTS;
 extern StringHash PSP_AMBIENTCOLOR;
 extern StringHash PSP_AMBIENTCOLOR;
 extern StringHash PSP_CAMERAPOS;
 extern StringHash PSP_CAMERAPOS;
 extern StringHash PSP_DELTATIME;
 extern StringHash PSP_DELTATIME;
+extern StringHash PSP_DEPTHRECONSTRUCT;
 extern StringHash PSP_ELAPSEDTIME;
 extern StringHash PSP_ELAPSEDTIME;
 extern StringHash PSP_FOGCOLOR;
 extern StringHash PSP_FOGCOLOR;
 extern StringHash PSP_FOGPARAMS;
 extern StringHash PSP_FOGPARAMS;

+ 13 - 0
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -171,6 +171,7 @@ static const unsigned MAX_FRAMEBUFFER_AGE = 2000;
 
 
 #ifdef GL_ES_VERSION_2_0
 #ifdef GL_ES_VERSION_2_0
 static unsigned glesDepthStencilFormat = GL_DEPTH_COMPONENT16;
 static unsigned glesDepthStencilFormat = GL_DEPTH_COMPONENT16;
+static unsigned glesReadableDepthFormat = GL_DEPTH_COMPONENT;
 #endif
 #endif
 
 
 bool CheckExtension(String& extensions, const String& name)
 bool CheckExtension(String& extensions, const String& name)
@@ -2589,6 +2590,15 @@ unsigned Graphics::GetDepthStencilFormat()
     #endif
     #endif
 }
 }
 
 
+unsigned Graphics::GetReadableDepthFormat()
+{
+    #ifndef GL_ES_VERSION_2_0
+    return GL_DEPTH_COMPONENT24;
+    #else
+    return glesReadableDepthFormat;
+    #endif
+}
+
 unsigned Graphics::GetFormat(const String& formatName)
 unsigned Graphics::GetFormat(const String& formatName)
 {
 {
     String nameLower = formatName.ToLower().Trimmed();
     String nameLower = formatName.ToLower().Trimmed();
@@ -2623,6 +2633,8 @@ unsigned Graphics::GetFormat(const String& formatName)
         return GetLinearDepthFormat();
         return GetLinearDepthFormat();
     if (nameLower == "d24s8")
     if (nameLower == "d24s8")
         return GetDepthStencilFormat();
         return GetDepthStencilFormat();
+    if (nameLower == "readabledepth" || nameLower == "hwdepth")
+        return GetReadableDepthFormat();
     
     
     return GetRGBFormat();
     return GetRGBFormat();
 }
 }
@@ -2676,6 +2688,7 @@ void Graphics::CheckFeatureSupport(String& extensions)
     {
     {
         shadowMapFormat_ = 0;
         shadowMapFormat_ = 0;
         hiresShadowMapFormat_ = 0;
         hiresShadowMapFormat_ = 0;
+        glesReadableDepthFormat = 0;
     }
     }
     else
     else
     {
     {

+ 4 - 0
Source/Urho3D/Graphics/OpenGL/OGLGraphics.h

@@ -287,6 +287,8 @@ public:
     bool GetAnisotropySupport() const { return anisotropySupport_; }
     bool GetAnisotropySupport() const { return anisotropySupport_; }
     /// Return whether shadow map depth compare is done in hardware. Always true on OpenGL.
     /// Return whether shadow map depth compare is done in hardware. Always true on OpenGL.
     bool GetHardwareShadowSupport() const { return true; }
     bool GetHardwareShadowSupport() const { return true; }
+    /// Return whether a readable hardware depth format is available.
+    bool GetReadableDepthSupport() const { return GetReadableDepthFormat() != 0; }
     /// Return whether stream offset is supported. Always true on OpenGL.
     /// Return whether stream offset is supported. Always true on OpenGL.
     bool GetStreamOffsetSupport() const { return true; }
     bool GetStreamOffsetSupport() const { return true; }
     /// Return whether sRGB conversion on texture sampling is supported.
     /// Return whether sRGB conversion on texture sampling is supported.
@@ -437,6 +439,8 @@ public:
     static unsigned GetLinearDepthFormat();
     static unsigned GetLinearDepthFormat();
     /// Return the API-specific hardware depth-stencil texture format.
     /// Return the API-specific hardware depth-stencil texture format.
     static unsigned GetDepthStencilFormat();
     static unsigned GetDepthStencilFormat();
+    /// Return the API-specific readable hardware depth format, or 0 if not supported.
+    static unsigned GetReadableDepthFormat();
     /// Return the API-specific texture format from a textual description, for example "rgb".
     /// Return the API-specific texture format from a textual description, for example "rgb".
     static unsigned GetFormat(const String& formatName);
     static unsigned GetFormat(const String& formatName);
     
     

+ 7 - 0
Source/Urho3D/Graphics/RenderPath.cpp

@@ -172,6 +172,8 @@ void RenderPathCommand::Load(const XMLElement& element)
     outputNames_.Push("viewport");
     outputNames_.Push("viewport");
     if (element.HasAttribute("output"))
     if (element.HasAttribute("output"))
         outputNames_[0] = element.GetAttribute("output");
         outputNames_[0] = element.GetAttribute("output");
+    if (element.HasAttribute("depthstencil"))
+        depthStencilName_ = element.GetAttribute("depthstencil");
     // Check for defining multiple outputs
     // Check for defining multiple outputs
     XMLElement outputElem = element.GetChild("output");
     XMLElement outputElem = element.GetChild("output");
     while (outputElem)
     while (outputElem)
@@ -232,6 +234,11 @@ void RenderPathCommand::SetOutputName(unsigned index, const String& name)
         outputNames_.Push(name);
         outputNames_.Push(name);
 }
 }
 
 
+void RenderPathCommand::SetDepthStencilName(const String& name)
+{
+    depthStencilName_ = name;
+}
+
 const String& RenderPathCommand::GetTextureName(TextureUnit unit) const
 const String& RenderPathCommand::GetTextureName(TextureUnit unit) const
 {
 {
     return unit < MAX_TEXTURE_UNITS ? textureNames_[unit] : String::EMPTY;
     return unit < MAX_TEXTURE_UNITS ? textureNames_[unit] : String::EMPTY;

+ 6 - 0
Source/Urho3D/Graphics/RenderPath.h

@@ -123,6 +123,8 @@ struct RenderPathCommand
     void SetNumOutputs(unsigned num);
     void SetNumOutputs(unsigned num);
     /// Set output rendertarget name.
     /// Set output rendertarget name.
     void SetOutputName(unsigned index, const String& name);
     void SetOutputName(unsigned index, const String& name);
+    /// Set depth-stencil output name. When empty, will assign a depth-stencil buffer automatically.
+    void SetDepthStencilName(const String& name);
     
     
     /// Return texture resource name.
     /// Return texture resource name.
     const String& GetTextureName(TextureUnit unit) const;
     const String& GetTextureName(TextureUnit unit) const;
@@ -132,6 +134,8 @@ struct RenderPathCommand
     unsigned GetNumOutputs() const { return outputNames_.Size(); }
     unsigned GetNumOutputs() const { return outputNames_.Size(); }
     /// Return output rendertarget name.
     /// Return output rendertarget name.
     const String& GetOutputName(unsigned index) const;
     const String& GetOutputName(unsigned index) const;
+    /// Return depth-stencil output name.
+    const String& GetDepthStencilName() const { return depthStencilName_; }
     
     
     /// Tag name.
     /// Tag name.
     String tag_;
     String tag_;
@@ -157,6 +161,8 @@ struct RenderPathCommand
     HashMap<StringHash, Variant> shaderParameters_;
     HashMap<StringHash, Variant> shaderParameters_;
     /// Output rendertarget names.
     /// Output rendertarget names.
     Vector<String> outputNames_;
     Vector<String> outputNames_;
+    /// Depth-stencil output name.
+    String depthStencilName_;
     /// Clear flags.
     /// Clear flags.
     unsigned clearFlags_;
     unsigned clearFlags_;
     /// Clear color.
     /// Clear color.

+ 1 - 1
Source/Urho3D/Graphics/Renderer.cpp

@@ -943,7 +943,7 @@ Texture2D* Renderer::GetShadowMap(Light* light, Camera* camera, unsigned viewWid
 
 
 Texture2D* Renderer::GetScreenBuffer(int width, int height, unsigned format, bool filtered, bool srgb, unsigned persistentKey)
 Texture2D* Renderer::GetScreenBuffer(int width, int height, unsigned format, bool filtered, bool srgb, unsigned persistentKey)
 {
 {
-    bool depthStencil = (format == Graphics::GetDepthStencilFormat());
+    bool depthStencil = (format == Graphics::GetDepthStencilFormat()) || (format == Graphics::GetReadableDepthFormat());
     if (depthStencil)
     if (depthStencil)
     {
     {
         filtered = false;
         filtered = false;

+ 58 - 6
Source/Urho3D/Graphics/View.cpp

@@ -567,9 +567,9 @@ void View::Render()
     IntRect viewport = (currentRenderTarget_ == renderTarget_) ? viewRect_ : IntRect(0, 0, rtSizeNow.x_,
     IntRect viewport = (currentRenderTarget_ == renderTarget_) ? viewRect_ : IntRect(0, 0, rtSizeNow.x_,
         rtSizeNow.y_);
         rtSizeNow.y_);
     graphics_->SetViewport(viewport);
     graphics_->SetViewport(viewport);
-    
     graphics_->SetFillMode(FILL_SOLID);
     graphics_->SetFillMode(FILL_SOLID);
     graphics_->SetClipPlane(false);
     graphics_->SetClipPlane(false);
+    graphics_->SetColorWrite(true);
     graphics_->SetDepthBias(0.0f, 0.0f);
     graphics_->SetDepthBias(0.0f, 0.0f);
     graphics_->SetScissorTest(false);
     graphics_->SetScissorTest(false);
     graphics_->SetStencilTest(false);
     graphics_->SetStencilTest(false);
@@ -661,6 +661,10 @@ void View::SetCameraShaderParameters(Camera* camera, bool setProjection, bool ov
         depthMode.w_ = 1.0f / camera->GetFarClip();
         depthMode.w_ = 1.0f / camera->GetFarClip();
     
     
     graphics_->SetShaderParameter(VSP_DEPTHMODE, depthMode);
     graphics_->SetShaderParameter(VSP_DEPTHMODE, depthMode);
+
+    Vector4 depthReconstruct(farClip / (farClip - nearClip), -nearClip / (farClip - nearClip), camera->IsOrthographic() ? 1.0f :
+        0.0f, camera->IsOrthographic() ? 0.0f : 1.0f);
+    graphics_->SetShaderParameter(PSP_DEPTHRECONSTRUCT, depthReconstruct);
     
     
     Vector3 nearVector, farVector;
     Vector3 nearVector, farVector;
     camera->GetFrustumSize(nearVector, farVector);
     camera->GetFrustumSize(nearVector, farVector);
@@ -1570,7 +1574,9 @@ void View::ExecuteRenderPathCommands()
 void View::SetRenderTargets(RenderPathCommand& command)
 void View::SetRenderTargets(RenderPathCommand& command)
 {
 {
     unsigned index = 0;
     unsigned index = 0;
-    
+    bool useColorWrite = true;
+    bool useCustomDepth = false;
+
     while (index < command.outputNames_.Size())
     while (index < command.outputNames_.Size())
     {
     {
         if (!command.outputNames_[index].Compare("viewport", false))
         if (!command.outputNames_[index].Compare("viewport", false))
@@ -1581,7 +1587,25 @@ void View::SetRenderTargets(RenderPathCommand& command)
             if (renderTargets_.Contains(nameHash))
             if (renderTargets_.Contains(nameHash))
             {
             {
                 Texture2D* texture = renderTargets_[nameHash];
                 Texture2D* texture = renderTargets_[nameHash];
-                graphics_->SetRenderTarget(index, texture);
+                // Check for depth only rendering (by specifying a depth texture as the sole output)
+                if (!index && command.outputNames_.Size() == 1 && texture && texture->GetFormat() == 
+                    Graphics::GetReadableDepthFormat() || texture->GetFormat() == Graphics::GetDepthStencilFormat())
+                {
+                    useColorWrite = false;
+                    useCustomDepth = true;
+                    #ifndef URHO3D_OPENGL
+                    // On D3D actual depth-only rendering is illegal, we need a color rendertarget
+                    if (!depthOnlyDummyTexture_)
+                    {
+                        depthOnlyDummyTexture_ = renderer_->GetScreenBuffer(texture->GetWidth(), texture->GetHeight(),
+                            graphics_->GetDummyColorFormat(), false, false);
+                    }
+                    #endif
+                    graphics_->SetRenderTarget(0, depthOnlyDummyTexture_); 
+                    graphics_->SetDepthStencil(texture);
+                }
+                else
+                    graphics_->SetRenderTarget(index, texture);
             }
             }
             else
             else
                 graphics_->SetRenderTarget(0, (RenderSurface*)0);
                 graphics_->SetRenderTarget(0, (RenderSurface*)0);
@@ -1596,15 +1620,26 @@ void View::SetRenderTargets(RenderPathCommand& command)
         ++index;
         ++index;
     }
     }
     
     
+    if (command.depthStencilName_.Length())
+    {
+        Texture2D* depthTexture = renderTargets_[StringHash(command.depthStencilName_)];
+        if (depthTexture)
+        {
+            useCustomDepth = true;
+            graphics_->SetDepthStencil(depthTexture);
+        }
+    }
+
     // When rendering to the final destination rendertarget, use the actual viewport. Otherwise texture rendertargets will be
     // When rendering to the final destination rendertarget, use the actual viewport. Otherwise texture rendertargets will be
     // viewport-sized, so they should use their full size as the viewport
     // viewport-sized, so they should use their full size as the viewport
     IntVector2 rtSizeNow = graphics_->GetRenderTargetDimensions();
     IntVector2 rtSizeNow = graphics_->GetRenderTargetDimensions();
     IntRect viewport = (graphics_->GetRenderTarget(0) == renderTarget_) ? viewRect_ : IntRect(0, 0, rtSizeNow.x_,
     IntRect viewport = (graphics_->GetRenderTarget(0) == renderTarget_) ? viewRect_ : IntRect(0, 0, rtSizeNow.x_,
         rtSizeNow.y_);
         rtSizeNow.y_);
     
     
-    graphics_->SetDepthStencil(GetDepthStencil(graphics_->GetRenderTarget(0)));
+    if (!useCustomDepth)
+        graphics_->SetDepthStencil(GetDepthStencil(graphics_->GetRenderTarget(0)));
     graphics_->SetViewport(viewport);
     graphics_->SetViewport(viewport);
-    graphics_->SetColorWrite(true);
+    graphics_->SetColorWrite(useColorWrite);
 }
 }
 
 
 void View::SetTextures(RenderPathCommand& command)
 void View::SetTextures(RenderPathCommand& command)
@@ -1777,6 +1812,7 @@ void View::AllocateScreenBuffers()
 {
 {
     bool needSubstitute = false;
     bool needSubstitute = false;
     unsigned numViewportTextures = 0;
     unsigned numViewportTextures = 0;
+    depthOnlyDummyTexture_ = 0;
 
 
     #ifdef URHO3D_OPENGL
     #ifdef URHO3D_OPENGL
     // Due to FBO limitations, in OpenGL deferred modes need to render to texture first and then blit to the backbuffer
     // Due to FBO limitations, in OpenGL deferred modes need to render to texture first and then blit to the backbuffer
@@ -1784,6 +1820,22 @@ void View::AllocateScreenBuffers()
     if ((deferred_ && !renderTarget_) || (deferredAmbient_ && renderTarget_ && renderTarget_->GetParentTexture()->GetFormat() !=
     if ((deferred_ && !renderTarget_) || (deferredAmbient_ && renderTarget_ && renderTarget_->GetParentTexture()->GetFormat() !=
         Graphics::GetRGBAFormat()))
         Graphics::GetRGBAFormat()))
         needSubstitute = true;
         needSubstitute = true;
+    // Also need substitute if rendering to backbuffer using a custom (readable) depth buffer
+    if (!renderTarget_ && !needSubstitute)
+    {
+        for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
+        {
+            const RenderPathCommand& command = renderPath_->commands_[i];
+            if (!IsNecessary(command))
+                continue;
+            if (command.depthStencilName_.Length() && command.outputNames_.Size() && !command.outputNames_[0].Compare("viewport",
+                false))
+            {
+                needSubstitute = true;
+                break;
+            }
+        }
+    }
     #endif
     #endif
     // If backbuffer is antialiased when using deferred rendering, need to reserve a buffer
     // If backbuffer is antialiased when using deferred rendering, need to reserve a buffer
     if (deferred_ && !renderTarget_ && graphics_->GetMultiSample() > 1)
     if (deferred_ && !renderTarget_ && graphics_->GetMultiSample() > 1)
@@ -1794,7 +1846,7 @@ void View::AllocateScreenBuffers()
     {
     {
         if (deferred_)
         if (deferred_)
             needSubstitute = true;
             needSubstitute = true;
-        else
+        else if (!needSubstitute)
         {
         {
             // Check also if using MRT without deferred rendering and rendering to the viewport and another texture
             // Check also if using MRT without deferred rendering and rendering to the viewport and another texture
             for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
             for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)

+ 2 - 0
Source/Urho3D/Graphics/View.h

@@ -283,6 +283,8 @@ private:
     RenderSurface* currentRenderTarget_;
     RenderSurface* currentRenderTarget_;
     /// Texture containing the latest viewport texture.
     /// Texture containing the latest viewport texture.
     Texture2D* currentViewportTexture_;
     Texture2D* currentViewportTexture_;
+    /// Dummy texture for D3D9 depth only rendering.
+    Texture2D* depthOnlyDummyTexture_;
     /// Viewport rectangle.
     /// Viewport rectangle.
     IntRect viewRect_;
     IntRect viewRect_;
     /// Viewport size.
     /// Viewport size.

+ 20 - 2
Source/Urho3D/LuaScript/pkgs/Graphics/Graphics.pkg

@@ -50,13 +50,30 @@ class Graphics : public Object
     bool GetLightPrepassSupport() const;
     bool GetLightPrepassSupport() const;
     bool GetDeferredSupport() const;
     bool GetDeferredSupport() const;
     bool GetHardwareShadowSupport() const;
     bool GetHardwareShadowSupport() const;
+    bool GetReadableDepthSupport() const;
     bool GetStreamOffsetSupport() const;
     bool GetStreamOffsetSupport() const;
     bool GetSRGBSupport() const;
     bool GetSRGBSupport() const;
     bool GetSRGBWriteSupport() const;
     bool GetSRGBWriteSupport() const;
     IntVector2 GetDesktopResolution() const;
     IntVector2 GetDesktopResolution() const;
-    
+
+    static unsigned GetAlphaFormat();
+    static unsigned GetLuminanceFormat();
+    static unsigned GetLuminanceAlphaFormat();
     static unsigned GetRGBFormat();
     static unsigned GetRGBFormat();
-    
+    static unsigned GetRGBAFormat();
+    static unsigned GetRGBA16Format();
+    static unsigned GetRGBAFloat16Format();
+    static unsigned GetRGBAFloat32Format();
+    static unsigned GetRG16Format();
+    static unsigned GetRGFloat16Format();
+    static unsigned GetRGFloat32Format();
+    static unsigned GetFloat16Format();
+    static unsigned GetFloat32Format();
+    static unsigned GetLinearDepthFormat();
+    static unsigned GetDepthStencilFormat();
+    static unsigned GetReadableDepthFormat();
+    static unsigned GetFormat(const String formatName);
+
     tolua_readonly tolua_property__is_set bool initialized;
     tolua_readonly tolua_property__is_set bool initialized;
     tolua_property__get_set String windowTitle;
     tolua_property__get_set String windowTitle;
     tolua_property__get_set IntVector2 windowPosition;
     tolua_property__get_set IntVector2 windowPosition;
@@ -82,6 +99,7 @@ class Graphics : public Object
     tolua_readonly tolua_property__get_set bool lightPrepassSupport;
     tolua_readonly tolua_property__get_set bool lightPrepassSupport;
     tolua_readonly tolua_property__get_set bool deferredSupport;
     tolua_readonly tolua_property__get_set bool deferredSupport;
     tolua_readonly tolua_property__get_set bool hardwareShadowSupport;
     tolua_readonly tolua_property__get_set bool hardwareShadowSupport;
+    tolua_readonly tolua_property__get_set bool readableDepthSupport;
     tolua_readonly tolua_property__get_set bool streamOffsetSupport;
     tolua_readonly tolua_property__get_set bool streamOffsetSupport;
     tolua_readonly tolua_property__get_set bool sRGBSupport;
     tolua_readonly tolua_property__get_set bool sRGBSupport;
     tolua_readonly tolua_property__get_set bool sRGBWriteSupport;
     tolua_readonly tolua_property__get_set bool sRGBWriteSupport;

+ 48 - 0
Source/Urho3D/LuaScript/pkgs/Graphics/RenderPath.pkg

@@ -1,5 +1,53 @@
 $#include "Graphics/RenderPath.h"
 $#include "Graphics/RenderPath.h"
 
 
+enum RenderCommandType
+{
+    CMD_NONE = 0,
+    CMD_CLEAR,
+    CMD_SCENEPASS,
+    CMD_QUAD,
+    CMD_FORWARDLIGHTS,
+    CMD_LIGHTVOLUMES
+};
+
+struct RenderPathCommand
+{
+    RenderPathCommand();
+    
+    void Load(const XMLElement& element);
+    void SetTextureName(TextureUnit unit, const String name);
+    void SetShaderParameter(const String name, const Variant& value);
+    void RemoveShaderParameter(const String name);
+    void SetNumOutputs(unsigned num);
+    void SetOutputName(unsigned index, const String& name);
+    void SetDepthStencilName(const String name);
+
+    const String GetTextureName(TextureUnit unit) const;
+    const Variant& GetShaderParameter(const String& name) const;
+    unsigned GetNumOutputs() const;
+    const String GetOutputName(unsigned index) const;
+    const String GetDepthStencilName() const;
+
+    String tag_ @ tag;
+    RenderCommandType type_ @ type;
+    RenderCommandSortMode sortMode_ @ sortMode;
+    String pass_ @ pass;
+    String metadata_ @ metadata;
+    String vertexShaderName_ @ vertexShaderName;
+    String pixelShaderName_ @ pixelShaderName;
+    String vertexShaderDefines_ @ vertexShaderDefines;
+    String pixelShaderDefines_ @ pixelShaderDefines;
+    unsigned clearFlags_ @ clearFlags;
+    Color clearColor_ @ clearColor;
+    float clearDepth_ @ clearDepth;
+    unsigned clearStencil_ @ clearStencil;
+    bool enabled_ @ enabled;
+    bool useFogColor_ @ useFogColor;
+    bool markToStencil_ @ markToStencil;
+    bool useLitBase_ @ useLitBase;
+    bool vertexLights_ @ vertexLights;
+};
+
 class RenderPath
 class RenderPath
 {
 {
     // SharedPtr<RenderPath> Clone();
     // SharedPtr<RenderPath> Clone();

+ 4 - 0
Source/Urho3D/Script/GraphicsAPI.cpp

@@ -326,6 +326,8 @@ static void RegisterRenderPath(asIScriptEngine* engine)
     engine->RegisterObjectMethod("RenderPathCommand", "uint get_numOutputs() const", asMETHOD(RenderPathCommand, GetNumOutputs), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderPathCommand", "uint get_numOutputs() const", asMETHOD(RenderPathCommand, GetNumOutputs), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderPathCommand", "void set_outputNames(uint, const String&in)", asMETHOD(RenderPathCommand, SetOutputName), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderPathCommand", "void set_outputNames(uint, const String&in)", asMETHOD(RenderPathCommand, SetOutputName), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderPathCommand", "const String& get_outputNames(uint) const", asMETHOD(RenderPathCommand, GetOutputName), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderPathCommand", "const String& get_outputNames(uint) const", asMETHOD(RenderPathCommand, GetOutputName), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RenderPathCommand", "void set_depthStencilName(const String&in)", asMETHOD(RenderPathCommand, SetDepthStencilName), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RenderPathCommand", "const String& get_depthStencilName() const", asMETHOD(RenderPathCommand, GetDepthStencilName), asCALL_THISCALL);
     engine->RegisterObjectProperty("RenderPathCommand", "String tag", offsetof(RenderPathCommand, tag_));
     engine->RegisterObjectProperty("RenderPathCommand", "String tag", offsetof(RenderPathCommand, tag_));
     engine->RegisterObjectProperty("RenderPathCommand", "RenderCommandType type", offsetof(RenderPathCommand, type_));
     engine->RegisterObjectProperty("RenderPathCommand", "RenderCommandType type", offsetof(RenderPathCommand, type_));
     engine->RegisterObjectProperty("RenderPathCommand", "RenderCommandSortMode sortMode", offsetof(RenderPathCommand, sortMode_));
     engine->RegisterObjectProperty("RenderPathCommand", "RenderCommandSortMode sortMode", offsetof(RenderPathCommand, sortMode_));
@@ -479,6 +481,7 @@ static void RegisterTextures(asIScriptEngine* engine)
     engine->RegisterGlobalFunction("uint GetFloat16Format()", asFUNCTION(Graphics::GetFloat16Format), asCALL_CDECL);
     engine->RegisterGlobalFunction("uint GetFloat16Format()", asFUNCTION(Graphics::GetFloat16Format), asCALL_CDECL);
     engine->RegisterGlobalFunction("uint GetFloat32Format()", asFUNCTION(Graphics::GetFloat32Format), asCALL_CDECL);
     engine->RegisterGlobalFunction("uint GetFloat32Format()", asFUNCTION(Graphics::GetFloat32Format), asCALL_CDECL);
     engine->RegisterGlobalFunction("uint GetDepthStencilFormat()", asFUNCTION(Graphics::GetDepthStencilFormat), asCALL_CDECL);
     engine->RegisterGlobalFunction("uint GetDepthStencilFormat()", asFUNCTION(Graphics::GetDepthStencilFormat), asCALL_CDECL);
+    engine->RegisterGlobalFunction("uint GetReadableDepthFormat()", asFUNCTION(Graphics::GetReadableDepthFormat), asCALL_CDECL);
     engine->RegisterGlobalFunction("uint GetFormat(const String&in)", asFUNCTIONPR(Graphics::GetFormat, (const String&), unsigned), asCALL_CDECL);
     engine->RegisterGlobalFunction("uint GetFormat(const String&in)", asFUNCTIONPR(Graphics::GetFormat, (const String&), unsigned), asCALL_CDECL);
 }
 }
 
 
@@ -1378,6 +1381,7 @@ static void RegisterGraphics(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Graphics", "bool get_lightPrepassSupport() const", asMETHOD(Graphics, GetLightPrepassSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_lightPrepassSupport() const", asMETHOD(Graphics, GetLightPrepassSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_deferredSupport() const", asMETHOD(Graphics, GetDeferredSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_deferredSupport() const", asMETHOD(Graphics, GetDeferredSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_hardwareShadowSupport() const", asMETHOD(Graphics, GetHardwareShadowSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_hardwareShadowSupport() const", asMETHOD(Graphics, GetHardwareShadowSupport), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Graphics", "bool get_readableDepthSupport() const", asMETHOD(Graphics, GetReadableDepthSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_sRGBSupport() const", asMETHOD(Graphics, GetSRGBSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_sRGBSupport() const", asMETHOD(Graphics, GetSRGBSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_sRGBWriteSupport() const", asMETHOD(Graphics, GetSRGBWriteSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_sRGBWriteSupport() const", asMETHOD(Graphics, GetSRGBWriteSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "void set_forceSM2(bool)", asMETHOD(Graphics, SetForceSM2), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "void set_forceSM2(bool)", asMETHOD(Graphics, SetForceSM2), asCALL_THISCALL);

+ 2 - 0
Source/Urho3D/UI/UI.cpp

@@ -751,10 +751,12 @@ void UI::Render(VertexBuffer* buffer, const PODVector<UIBatch>& batches, unsigne
     projection.m33_ = 1.0f;
     projection.m33_ = 1.0f;
 
 
     graphics_->ClearParameterSources();
     graphics_->ClearParameterSources();
+    graphics_->SetColorWrite(true);
     graphics_->SetCullMode(CULL_CCW);
     graphics_->SetCullMode(CULL_CCW);
     graphics_->SetDepthTest(CMP_ALWAYS);
     graphics_->SetDepthTest(CMP_ALWAYS);
     graphics_->SetDepthWrite(false);
     graphics_->SetDepthWrite(false);
     graphics_->SetDrawAntialiased(false);
     graphics_->SetDrawAntialiased(false);
+    graphics_->SetFillMode(FILL_SOLID);
     graphics_->SetStencilTest(false);
     graphics_->SetStencilTest(false);
     graphics_->ResetRenderTargets();
     graphics_->ResetRenderTargets();
     graphics_->SetVertexBuffer(buffer);
     graphics_->SetVertexBuffer(buffer);