Browse Source

Avoid unnecessary rendertarget blitting in OpenGL light prepass mode.
Fixed too dark ambient lighting and environment cube mapping in OpenGL deferred mode.
Added new shader function GetQuadTexCoordNoFlip() which can be used to sample regular texture resources in postprocessing quad passes and documented it.
Removed Camera::SetFlipVertical() from the Lua script API as it should only be called internally to handle OpenGL / Direct3D9 differences.

Lasse Öörni 12 years ago
parent
commit
0f5456d35e

+ 5 - 5
Bin/CoreData/Shaders/GLSL/LitSolid.frag

@@ -91,7 +91,7 @@ void main()
         #else
         #else
             finalColor = diff * lightColor * diffColor.rgb;
             finalColor = diff * lightColor * diffColor.rgb;
         #endif
         #endif
-    
+
         #ifdef AMBIENT
         #ifdef AMBIENT
             finalColor += cAmbientColor * diffColor.rgb;
             finalColor += cAmbientColor * diffColor.rgb;
             gl_FragColor = vec4(GetFog(finalColor, vLightVec.w), diffColor.a);
             gl_FragColor = vec4(GetFog(finalColor, vLightVec.w), diffColor.a);
@@ -106,9 +106,9 @@ void main()
         #else
         #else
             vec3 normal = vNormal;
             vec3 normal = vNormal;
         #endif
         #endif
-    
+
         float specPower = cMatSpecColor.a / 255.0;
         float specPower = cMatSpecColor.a / 255.0;
-        
+
         gl_FragData[0] = vec4(normal * 0.5 + 0.5, specPower);
         gl_FragData[0] = vec4(normal * 0.5 + 0.5, specPower);
         gl_FragData[1] = vec4(EncodeDepth(vVertexLight.a), 0.0);
         gl_FragData[1] = vec4(EncodeDepth(vVertexLight.a), 0.0);
     #elif defined(DEFERRED)
     #elif defined(DEFERRED)
@@ -127,13 +127,13 @@ void main()
 
 
         #ifdef ENVCUBEMAP
         #ifdef ENVCUBEMAP
             normal = normalize(normal);
             normal = normalize(normal);
-            finalColor += cMatEnvMapColor * textureCube(sEnvCubeMap, reflect(vReflectionVec, normal)).rgb;
+            finalColor = cMatEnvMapColor * textureCube(sEnvCubeMap, reflect(vReflectionVec, normal)).rgb;
         #endif
         #endif
         #ifdef LIGHTMAP
         #ifdef LIGHTMAP
             finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * diffColor.rgb;
             finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * diffColor.rgb;
         #endif
         #endif
 
 
-        gl_FragData[0] = vec4(GetFog(finalColor * diffColor.rgb, vVertexLight.a), 1.0);
+        gl_FragData[0] = vec4(GetFog(finalColor, vVertexLight.a), 1.0);
         gl_FragData[1] = GetFogFactor(vVertexLight.a) * vec4(diffColor.rgb, specIntensity);
         gl_FragData[1] = GetFogFactor(vVertexLight.a) * vec4(diffColor.rgb, specIntensity);
         gl_FragData[2] = vec4(normal * 0.5 + 0.5, specPower);
         gl_FragData[2] = vec4(normal * 0.5 + 0.5, specPower);
         gl_FragData[3] = vec4(EncodeDepth(vVertexLight.a), 0.0);
         gl_FragData[3] = vec4(EncodeDepth(vVertexLight.a), 0.0);

+ 7 - 0
Bin/CoreData/Shaders/GLSL/ScreenPos.vert

@@ -21,6 +21,13 @@ vec2 GetQuadTexCoord(vec4 clipPos)
         clipPos.y / clipPos.w * 0.5 + 0.5);
         clipPos.y / clipPos.w * 0.5 + 0.5);
 }
 }
 
 
+vec2 GetQuadTexCoordNoFlip(vec3 worldPos)
+{
+    return vec2(
+        worldPos.x * 0.5 + 0.5,
+        worldPos.y * 0.5 + 0.5);
+}
+
 vec3 GetFarRay(vec4 clipPos)
 vec3 GetFarRay(vec4 clipPos)
 {
 {
     vec3 viewRay = vec3(
     vec3 viewRay = vec3(

+ 7 - 0
Bin/CoreData/Shaders/HLSL/ScreenPos.hlsl

@@ -21,6 +21,13 @@ float2 GetQuadTexCoord(float4 clipPos)
         -clipPos.y / clipPos.w * 0.5 + 0.5);
         -clipPos.y / clipPos.w * 0.5 + 0.5);
 }
 }
 
 
+float2 GetQuadTexCoordNoFlip(float3 worldPos)
+{
+    return float2(
+        worldPos.x * 0.5 + 0.5,
+        -worldPos.y * 0.5 + 0.5);
+}
+
 float3 GetFarRay(float4 clipPos)
 float3 GetFarRay(float4 clipPos)
 {
 {
     float3 viewRay = float3(
     float3 viewRay = float3(

+ 0 - 3
Docs/LuaScriptAPI.dox

@@ -1263,7 +1263,6 @@ Methods:<br>
 - void SetOrthographic(bool enable)
 - void SetOrthographic(bool enable)
 - void SetAutoAspectRatio(bool enable)
 - void SetAutoAspectRatio(bool enable)
 - void SetProjectionOffset(const Vector2& offset)
 - void SetProjectionOffset(const Vector2& offset)
-- void SetFlipVertical(bool enable)
 - float GetFarClip() const
 - float GetFarClip() const
 - float GetNearClip() const
 - float GetNearClip() const
 - float GetFov() const
 - float GetFov() const
@@ -1292,7 +1291,6 @@ Methods:<br>
 - Vector3 GetRightVector() const
 - Vector3 GetRightVector() const
 - Vector3 GetUpVector() const
 - Vector3 GetUpVector() const
 - const Vector2& GetProjectionOffset() const
 - const Vector2& GetProjectionOffset() const
-- bool GetFlipVertical() const
 - float GetDistance(const Vector3& worldPos) const
 - float GetDistance(const Vector3& worldPos) const
 - float GetDistanceSquared(const Vector3& worldPos) const
 - float GetDistanceSquared(const Vector3& worldPos) const
 - float GetLodDistance(float distance, float scale, float bias) const
 - float GetLodDistance(float distance, float scale, float bias) const
@@ -1320,7 +1318,6 @@ Properties:<br>
 - Vector3 rightVector (readonly)
 - Vector3 rightVector (readonly)
 - Vector3 upVector (readonly)
 - Vector3 upVector (readonly)
 - Vector2& projectionOffset
 - Vector2& projectionOffset
-- bool flipVertical
 - bool projectionValid (readonly)
 - bool projectionValid (readonly)
 
 
 DebugRenderer : Component
 DebugRenderer : Component

+ 6 - 0
Docs/Reference.dox

@@ -945,6 +945,12 @@ Otherwise fully customized scene render passes can be specified, but there are a
 - Remember to mark the lighting mode (per-vertex / per-pixel) into the techniques which define custom passes, as the lighting mode can be guessed automatically only for the known default passes.
 - Remember to mark the lighting mode (per-vertex / per-pixel) into the techniques which define custom passes, as the lighting mode can be guessed automatically only for the known default passes.
 - The forwardlights command can optionally disable the lit base pass optimization without having to touch the material techniques, if a separate opaque ambient-only base pass is needed. By default the optimization is enabled.
 - The forwardlights command can optionally disable the lit base pass optimization without having to touch the material techniques, if a separate opaque ambient-only base pass is needed. By default the optimization is enabled.
 
 
+\section RenderPaths_PostProcess Post-processing effects special considerations
+
+Post-processing effects are usually implemented by using the quad command. When using intermediate rendertargets that are of different size than the viewport rendertarget, it is necessary in shaders to reference their (inverse) size and the half-pixel offset for Direct3D9. These shader uniforms are automatically generated for named rendertargets. For an example look at the bloom postprocess shaders: the rendertarget called HBlur will define the shader uniforms cHBlurInvSize and cHBlurOffsets (both Vector2.)
+
+In OpenGL post-processing shaders it is important to distinguish between sampling a rendertarget texture and a regular texture resource, because intermediate rendertargets (such as the G-buffer) may be vertically inverted. Use the GetScreenPos() or GetQuadTexCoord() functions to get rendertarget UV coordinates from the clip coordinates; this takes flipping into account automatically. For sampling a regular texture, use GetQuadTexCoordNoFlip() function, which requires world coordinates instead of clip coordinates.
+
 \page Lights Lights and shadows
 \page Lights Lights and shadows
 
 
 Lights in Urho3D can be directional, point, or spot lights. Shadow mapping is supported for all light types.
 Lights in Urho3D can be directional, point, or spot lights. Shadow mapping is supported for all light types.

+ 17 - 6
Source/Engine/Graphics/View.cpp

@@ -382,12 +382,26 @@ bool View::Define(RenderSurface* renderTarget, Viewport* viewport)
     
     
     // Get light volume shaders according to the renderpath, if it needs them
     // Get light volume shaders according to the renderpath, if it needs them
     deferred_ = false;
     deferred_ = false;
+    deferredAmbient_ = false;
     for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
     for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
     {
     {
         const RenderPathCommand& command = renderPath_->commands_[i];
         const RenderPathCommand& command = renderPath_->commands_[i];
         if (!command.enabled_)
         if (!command.enabled_)
             continue;
             continue;
         
         
+        // Check if ambient pass and G-buffer rendering happens at the same time
+        if (command.type_ == CMD_SCENEPASS && command.outputNames_.Size() > 1)
+        {
+            for (unsigned j = 0; j < command.outputNames_.Size(); ++j)
+            {
+                if (!command.outputNames_[j].Compare("viewport", false))
+                {
+                    deferredAmbient_ = true;
+                    break;
+                }
+            }
+        }
+        
         if (command.type_ == CMD_LIGHTVOLUMES)
         if (command.type_ == CMD_LIGHTVOLUMES)
         {
         {
             renderer_->GetLightVolumeShaders(lightVS_, lightPS_, command.vertexShaderName_, command.pixelShaderName_);
             renderer_->GetLightVolumeShaders(lightVS_, lightPS_, command.vertexShaderName_, command.pixelShaderName_);
@@ -1247,10 +1261,7 @@ void View::ExecuteRenderPathCommands()
                     
                     
                     // If this is a scene render pass, must copy the previous viewport contents now
                     // If this is a scene render pass, must copy the previous viewport contents now
                     if (command.type_ == CMD_SCENEPASS && !needResolve)
                     if (command.type_ == CMD_SCENEPASS && !needResolve)
-                    {
                         BlitFramebuffer(screenBuffers_[readBuffer_], screenBuffers_[writeBuffer_]->GetRenderSurface(), false);
                         BlitFramebuffer(screenBuffers_[readBuffer_], screenBuffers_[writeBuffer_]->GetRenderSurface(), false);
-                    }
-                    
                 }
                 }
                 
                 
                 // Resolve multisampled framebuffer now if necessary
                 // Resolve multisampled framebuffer now if necessary
@@ -1568,9 +1579,9 @@ void View::AllocateScreenBuffers()
     unsigned neededBuffers = 0;
     unsigned neededBuffers = 0;
     #ifdef USE_OPENGL
     #ifdef USE_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
-    // Also, if rendering to a texture with deferred rendering, it must be RGBA to comply with the rest of the buffers.
-    if (deferred_ && (!renderTarget_ || (deferred_ && renderTarget_->GetParentTexture()->GetFormat() != 
-        Graphics::GetRGBAFormat())))
+    // Also, if rendering to a texture with full deferred rendering, it must be RGBA to comply with the rest of the buffers.
+    if ((deferred_ && !renderTarget_) || (deferredAmbient_ && renderTarget_ && renderTarget_->GetParentTexture()->GetFormat() !=
+        Graphics::GetRGBAFormat()))
         neededBuffers = 1;
         neededBuffers = 1;
     #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

+ 3 - 1
Source/Engine/Graphics/View.h

@@ -233,7 +233,7 @@ private:
     OcclusionBuffer* occlusionBuffer_;
     OcclusionBuffer* occlusionBuffer_;
     /// Destination color rendertarget.
     /// Destination color rendertarget.
     RenderSurface* renderTarget_;
     RenderSurface* renderTarget_;
-    /// Effective color rendertarget to use, may be different if screenbuffers are used.
+    /// Color rendertarget active for the current renderpath command.
     RenderSurface* currentRenderTarget_;
     RenderSurface* currentRenderTarget_;
     /// Viewport rectangle.
     /// Viewport rectangle.
     IntRect viewRect_;
     IntRect viewRect_;
@@ -265,6 +265,8 @@ private:
     bool drawShadows_;
     bool drawShadows_;
     /// Deferred flag. Inferred from the existence of a light volume command in the renderpath.
     /// Deferred flag. Inferred from the existence of a light volume command in the renderpath.
     bool deferred_;
     bool deferred_;
+    /// Deferred ambient pass flag. This means that the destination rendertarget is being written to at the same time as albedo/normal/depth buffers, and needs to be RGBA on OpenGL.
+    bool deferredAmbient_;
     /// Renderpath.
     /// Renderpath.
     RenderPath* renderPath_;
     RenderPath* renderPath_;
     /// Intermediate screen buffers used in pingpong copies and OpenGL deferred framebuffer blit.
     /// Intermediate screen buffers used in pingpong copies and OpenGL deferred framebuffer blit.

+ 1 - 4
Source/Extras/LuaScript/pkgs/Graphics/Camera.pkg

@@ -18,8 +18,7 @@ class Camera : public Component
     void SetOrthographic(bool enable);
     void SetOrthographic(bool enable);
     void SetAutoAspectRatio(bool enable);
     void SetAutoAspectRatio(bool enable);
     void SetProjectionOffset(const Vector2& offset);
     void SetProjectionOffset(const Vector2& offset);
-    void SetFlipVertical(bool enable);
-    
+
     float GetFarClip() const;
     float GetFarClip() const;
     float GetNearClip() const;
     float GetNearClip() const;
     float GetFov() const;
     float GetFov() const;
@@ -48,7 +47,6 @@ class Camera : public Component
     Vector3 GetRightVector() const;
     Vector3 GetRightVector() const;
     Vector3 GetUpVector() const;
     Vector3 GetUpVector() const;
     const Vector2& GetProjectionOffset() const;
     const Vector2& GetProjectionOffset() const;
-    bool GetFlipVertical() const;
     float GetDistance(const Vector3& worldPos) const;
     float GetDistance(const Vector3& worldPos) const;
     float GetDistanceSquared(const Vector3& worldPos) const;
     float GetDistanceSquared(const Vector3& worldPos) const;
     float GetLodDistance(float distance, float scale, float bias) const;
     float GetLodDistance(float distance, float scale, float bias) const;
@@ -75,7 +73,6 @@ class Camera : public Component
     tolua_readonly tolua_property__get_set Vector3 rightVector;
     tolua_readonly tolua_property__get_set Vector3 rightVector;
     tolua_readonly tolua_property__get_set Vector3 upVector;
     tolua_readonly tolua_property__get_set Vector3 upVector;
     tolua_property__get_set Vector2& projectionOffset;
     tolua_property__get_set Vector2& projectionOffset;
-    tolua_property__get_set bool flipVertical;
     tolua_readonly tolua_property__is_set bool projectionValid;
     tolua_readonly tolua_property__is_set bool projectionValid;
 };
 };