Răsfoiți Sursa

Store camera projection matrix as API-independent and convert as necessary (preparation for allowing the user to define a custom projection matrix.) Camera GetProjection() API changed; GetGPUProjection() is now used to get the API-specific projection for use as a shader parameter.

Lasse Öörni 9 ani în urmă
părinte
comite
48cd15bc5a

+ 2 - 1
Source/Urho3D/AngelScript/GraphicsAPI.cpp

@@ -120,7 +120,8 @@ static void RegisterCamera(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Camera", "void set_fillMode(FillMode)", asMETHOD(Camera, SetFillMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "void set_fillMode(FillMode)", asMETHOD(Camera, SetFillMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "FillMode get_fillMode() const", asMETHOD(Camera, GetFillMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "FillMode get_fillMode() const", asMETHOD(Camera, GetFillMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "const Frustum& get_frustum() const", asMETHOD(Camera, GetFrustum), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "const Frustum& get_frustum() const", asMETHOD(Camera, GetFrustum), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Camera", "const Matrix4& get_projection() const", asMETHODPR(Camera, GetProjection, () const, const Matrix4&), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Camera", "Matrix4 get_projection() const", asMETHOD(Camera, GetProjection), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Camera", "Matrix4 get_gpuProjection() const", asMETHOD(Camera, GetGPUProjection), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "const Matrix3x4& get_view() const", asMETHOD(Camera, GetView), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "const Matrix3x4& get_view() const", asMETHOD(Camera, GetView), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "Frustum get_viewSpaceFrustum() const", asMETHOD(Camera, GetViewSpaceFrustum), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "Frustum get_viewSpaceFrustum() const", asMETHOD(Camera, GetViewSpaceFrustum), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "float get_halfViewSize() const", asMETHOD(Camera, GetHalfViewSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "float get_halfViewSize() const", asMETHOD(Camera, GetHalfViewSize), asCALL_THISCALL);

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

@@ -86,7 +86,7 @@ void CalculateShadowMatrix(Matrix4& dest, LightBatchQueue* queue, unsigned split
     const IntRect& viewport = queue->shadowSplits_[split].shadowViewport_;
     const IntRect& viewport = queue->shadowSplits_[split].shadowViewport_;
 
 
     Matrix3x4 shadowView(shadowCamera->GetView());
     Matrix3x4 shadowView(shadowCamera->GetView());
-    Matrix4 shadowProj(shadowCamera->GetProjection());
+    Matrix4 shadowProj(shadowCamera->GetGPUProjection());
     Matrix4 texAdjust(Matrix4::IDENTITY);
     Matrix4 texAdjust(Matrix4::IDENTITY);
 
 
     Texture2D* shadowMap = queue->shadowMap_;
     Texture2D* shadowMap = queue->shadowMap_;

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

@@ -736,7 +736,7 @@ void BillboardSet::CalculateFixedScreenSize(const FrameInfo& frame)
 
 
     if (!frame.camera_->IsOrthographic())
     if (!frame.camera_->IsOrthographic())
     {
     {
-        Matrix4 viewProj(frame.camera_->GetProjection(false) * frame.camera_->GetView());
+        Matrix4 viewProj(frame.camera_->GetProjection() * frame.camera_->GetView());
         const Matrix3x4& worldTransform = node_->GetWorldTransform();
         const Matrix3x4& worldTransform = node_->GetWorldTransform();
         Matrix3x4 billboardTransform = relative_ ? worldTransform : Matrix3x4::IDENTITY;
         Matrix3x4 billboardTransform = relative_ ? worldTransform : Matrix3x4::IDENTITY;
 
 

+ 48 - 68
Source/Urho3D/Graphics/Camera.cpp

@@ -249,7 +249,6 @@ void Camera::SetClipPlane(const Plane& plane)
 void Camera::SetFlipVertical(bool enable)
 void Camera::SetFlipVertical(bool enable)
 {
 {
     flipVertical_ = enable;
     flipVertical_ = enable;
-    projectionDirty_ = true;
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
@@ -322,7 +321,7 @@ Ray Camera::GetScreenRay(float x, float y) const
         return ret;
         return ret;
     }
     }
 
 
-    Matrix4 viewProjInverse = (GetProjection(false) * GetView()).Inverse();
+    Matrix4 viewProjInverse = (GetProjection() * GetView()).Inverse();
 
 
     // The parameters range from 0.0 to 1.0. Expand to normalized device coordinates (-1.0 to 1.0) & flip Y axis
     // The parameters range from 0.0 to 1.0. Expand to normalized device coordinates (-1.0 to 1.0) & flip Y axis
     x = 2.0f * x - 1.0f;
     x = 2.0f * x - 1.0f;
@@ -342,7 +341,7 @@ Vector2 Camera::WorldToScreenPoint(const Vector3& worldPos) const
 
 
     if (eyeSpacePos.z_ > 0.0f)
     if (eyeSpacePos.z_ > 0.0f)
     {
     {
-        Vector3 screenSpacePos = GetProjection(false) * eyeSpacePos;
+        Vector3 screenSpacePos = GetProjection() * eyeSpacePos;
         ret.x_ = screenSpacePos.x_;
         ret.x_ = screenSpacePos.x_;
         ret.y_ = screenSpacePos.y_;
         ret.y_ = screenSpacePos.y_;
     }
     }
@@ -382,85 +381,66 @@ const Frustum& Camera::GetFrustum() const
     return frustum_;
     return frustum_;
 }
 }
 
 
-const Matrix4& Camera::GetProjection() const
+Matrix4 Camera::GetProjection() const
 {
 {
     if (projectionDirty_)
     if (projectionDirty_)
     {
     {
-        projection_ = GetProjection(true);
-        projectionDirty_ = false;
-    }
-
-    return projection_;
-}
-
-Matrix4 Camera::GetProjection(bool apiSpecific) const
-{
-    Matrix4 ret(Matrix4::ZERO);
-
-    // Whether to construct matrix using OpenGL or Direct3D clip space convention
-#ifdef URHO3D_OPENGL
-    bool openGLFormat = apiSpecific;
-#else
-    bool openGLFormat = false;
-#endif
-
-    if (!orthographic_)
-    {
-        float nearClip = GetNearClip();
-        float h = (1.0f / tanf(fov_ * M_DEGTORAD * 0.5f)) * zoom_;
-        float w = h / aspectRatio_;
-        float q, r;
-
-        if (openGLFormat)
+        if (!orthographic_)
         {
         {
-            q = (farClip_ + nearClip) / (farClip_ - nearClip);
-            r = -2.0f * farClip_ * nearClip / (farClip_ - nearClip);
+            float nearClip = GetNearClip();
+            float h = (1.0f / tanf(fov_ * M_DEGTORAD * 0.5f)) * zoom_;
+            float w = h / aspectRatio_;
+            float q = farClip_ / (farClip_ - nearClip);
+            float r = -q * nearClip;
+
+            projection_.m00_ = w;
+            projection_.m02_ = projectionOffset_.x_ * 2.0f;
+            projection_.m11_ = h;
+            projection_.m12_ = projectionOffset_.y_ * 2.0f;
+            projection_.m22_ = q;
+            projection_.m23_ = r;
+            projection_.m32_ = 1.0f;
+            projection_.m33_ = 0.0f;
         }
         }
         else
         else
         {
         {
-            q = farClip_ / (farClip_ - nearClip);
-            r = -q * nearClip;
+            // Disregard near clip, because it does not affect depth precision as with perspective projection
+            float h = (1.0f / (orthoSize_ * 0.5f)) * zoom_;
+            float w = h / aspectRatio_;
+            float q = 1.0f / farClip_;
+            float r = 0.0f;
+
+            projection_.m00_ = w;
+            projection_.m03_ = projectionOffset_.x_ * 2.0f;
+            projection_.m11_ = h;
+            projection_.m13_ = projectionOffset_.y_ * 2.0f;
+            projection_.m22_ = q;
+            projection_.m23_ = r;
+            projection_.m32_ = 0.0f;
+            projection_.m33_ = 1.0f;
         }
         }
 
 
-        ret.m00_ = w;
-        ret.m02_ = projectionOffset_.x_ * 2.0f;
-        ret.m11_ = h;
-        ret.m12_ = projectionOffset_.y_ * 2.0f;
-        ret.m22_ = q;
-        ret.m23_ = r;
-        ret.m32_ = 1.0f;
+        projectionDirty_ = false;
     }
     }
-    else
-    {
-        // Disregard near clip, because it does not affect depth precision as with perspective projection
-        float h = (1.0f / (orthoSize_ * 0.5f)) * zoom_;
-        float w = h / aspectRatio_;
-        float q, r;
 
 
-        if (openGLFormat)
-        {
-            q = 2.0f / farClip_;
-            r = -1.0f;
-        }
-        else
-        {
-            q = 1.0f / farClip_;
-            r = 0.0f;
-        }
-
-        ret.m00_ = w;
-        ret.m03_ = projectionOffset_.x_ * 2.0f;
-        ret.m11_ = h;
-        ret.m13_ = projectionOffset_.y_ * 2.0f;
-        ret.m22_ = q;
-        ret.m23_ = r;
-        ret.m33_ = 1.0f;
-    }
+    return flipVertical_ ? flipMatrix * projection_ : projection_;
+}
 
 
-    if (flipVertical_)
-        ret = flipMatrix * ret;
+Matrix4 Camera::GetGPUProjection() const
+{
+#ifndef URHO3D_OPENGL
+    return GetProjection(); // Already matches API-specific format
+#else
+    // See formulation for depth range conversion at http://www.ogre3d.org/forums/viewtopic.php?f=4&t=13357
+    Matrix4 ret = GetProjection();
+    
+    ret.m20_ = 2.0f * ret.m20_ - ret.m30_;
+    ret.m21_ = 2.0f * ret.m21_ - ret.m31_;
+    ret.m22_ = 2.0f * ret.m22_ - ret.m32_;
+    ret.m23_ = 2.0f * ret.m23_ - ret.m33_;
 
 
     return ret;
     return ret;
+#endif
 }
 }
 
 
 void Camera::GetFrustumSize(Vector3& near, Vector3& far) const
 void Camera::GetFrustumSize(Vector3& near, Vector3& far) const

+ 4 - 4
Source/Urho3D/Graphics/Camera.h

@@ -133,10 +133,10 @@ public:
 
 
     /// Return frustum in world space.
     /// Return frustum in world space.
     const Frustum& GetFrustum() const;
     const Frustum& GetFrustum() const;
-    /// Return API-specific projection matrix.
-    const Matrix4& GetProjection() const;
-    /// Return either API-specific or API-independent (D3D convention) projection matrix.
-    Matrix4 GetProjection(bool apiSpecific) const;
+    /// Return projection matrix. It's in D3D convention with depth range 0-1.
+    Matrix4 GetProjection() const;
+    /// Return projection matrix converted to API-specific format for use as a shader parameter.
+    Matrix4 GetGPUProjection() const;
     /// Return view matrix.
     /// Return view matrix.
     const Matrix3x4& GetView() const;
     const Matrix3x4& GetView() const;
     /// Return frustum near and far sizes.
     /// Return frustum near and far sizes.

+ 2 - 1
Source/Urho3D/Graphics/DebugRenderer.cpp

@@ -71,6 +71,7 @@ void DebugRenderer::SetView(Camera* camera)
 
 
     view_ = camera->GetView();
     view_ = camera->GetView();
     projection_ = camera->GetProjection();
     projection_ = camera->GetProjection();
+    gpuProjection_ = camera->GetGPUProjection();
     frustum_ = camera->GetFrustum();
     frustum_ = camera->GetFrustum();
 }
 }
 
 
@@ -500,7 +501,7 @@ void DebugRenderer::Render()
     graphics->SetShaderParameter(VSP_MODEL, Matrix3x4::IDENTITY);
     graphics->SetShaderParameter(VSP_MODEL, Matrix3x4::IDENTITY);
     graphics->SetShaderParameter(VSP_VIEW, view_);
     graphics->SetShaderParameter(VSP_VIEW, view_);
     graphics->SetShaderParameter(VSP_VIEWINV, view_.Inverse());
     graphics->SetShaderParameter(VSP_VIEWINV, view_.Inverse());
-    graphics->SetShaderParameter(VSP_VIEWPROJ, projection_ * view_);
+    graphics->SetShaderParameter(VSP_VIEWPROJ, gpuProjection_ * view_);
     graphics->SetShaderParameter(PSP_MATDIFFCOLOR, Color(1.0f, 1.0f, 1.0f, 1.0f));
     graphics->SetShaderParameter(PSP_MATDIFFCOLOR, Color(1.0f, 1.0f, 1.0f, 1.0f));
     graphics->SetVertexBuffer(vertexBuffer_);
     graphics->SetVertexBuffer(vertexBuffer_);
 
 

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

@@ -174,6 +174,8 @@ private:
     Matrix3x4 view_;
     Matrix3x4 view_;
     /// Projection transform.
     /// Projection transform.
     Matrix4 projection_;
     Matrix4 projection_;
+    /// Projection transform in API-specific format.
+    Matrix4 gpuProjection_;
     /// View frustum.
     /// View frustum.
     Frustum frustum_;
     Frustum frustum_;
     /// Vertex buffer.
     /// Vertex buffer.

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

@@ -125,7 +125,7 @@ void OcclusionBuffer::SetView(Camera* camera)
         return;
         return;
 
 
     view_ = camera->GetView();
     view_ = camera->GetView();
-    projection_ = camera->GetProjection(false);
+    projection_ = camera->GetProjection();
     viewProj_ = projection_ * view_;
     viewProj_ = projection_ * view_;
     nearClip_ = camera->GetNearClip();
     nearClip_ = camera->GetNearClip();
     farClip_ = camera->GetFarClip();
     farClip_ = camera->GetFarClip();

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

@@ -1400,7 +1400,7 @@ void Renderer::OptimizeLightByStencil(Light* light, Camera* camera)
 
 
         Geometry* geometry = GetLightGeometry(light);
         Geometry* geometry = GetLightGeometry(light);
         const Matrix3x4& view = camera->GetView();
         const Matrix3x4& view = camera->GetView();
-        const Matrix4& projection = camera->GetProjection();
+        const Matrix4& projection = camera->GetGPUProjection();
         Vector3 cameraPos = camera->GetNode()->GetWorldPosition();
         Vector3 cameraPos = camera->GetNode()->GetWorldPosition();
         float lightDist;
         float lightDist;
 
 

+ 3 - 3
Source/Urho3D/Graphics/View.cpp

@@ -746,7 +746,7 @@ void View::SetCameraShaderParameters(Camera* camera)
     camera->GetFrustumSize(nearVector, farVector);
     camera->GetFrustumSize(nearVector, farVector);
     graphics_->SetShaderParameter(VSP_FRUSTUMSIZE, farVector);
     graphics_->SetShaderParameter(VSP_FRUSTUMSIZE, farVector);
 
 
-    Matrix4 projection = camera->GetProjection();
+    Matrix4 projection = camera->GetGPUProjection();
 #ifdef URHO3D_OPENGL
 #ifdef URHO3D_OPENGL
     // Add constant depth bias manually to the projection matrix due to glPolygonOffset() inconsistency
     // Add constant depth bias manually to the projection matrix due to glPolygonOffset() inconsistency
     float constantBias = 2.0f * graphics_->GetDepthConstantBias();
     float constantBias = 2.0f * graphics_->GetDepthConstantBias();
@@ -1565,7 +1565,7 @@ void View::ExecuteRenderPathCommands()
                         SetRenderTargets(command);
                         SetRenderTargets(command);
                         bool allowDepthWrite = SetTextures(command);
                         bool allowDepthWrite = SetTextures(command);
                         graphics_->SetClipPlane(camera_->GetUseClipping(), camera_->GetClipPlane(), camera_->GetView(),
                         graphics_->SetClipPlane(camera_->GetUseClipping(), camera_->GetClipPlane(), camera_->GetView(),
-                            camera_->GetProjection());
+                            camera_->GetGPUProjection());
                         queue.Draw(this, camera_, command.markToStencil_, false, allowDepthWrite);
                         queue.Draw(this, camera_, command.markToStencil_, false, allowDepthWrite);
                     }
                     }
                 }
                 }
@@ -1600,7 +1600,7 @@ void View::ExecuteRenderPathCommands()
 
 
                         bool allowDepthWrite = SetTextures(command);
                         bool allowDepthWrite = SetTextures(command);
                         graphics_->SetClipPlane(camera_->GetUseClipping(), camera_->GetClipPlane(), camera_->GetView(),
                         graphics_->SetClipPlane(camera_->GetUseClipping(), camera_->GetClipPlane(), camera_->GetView(),
-                            camera_->GetProjection());
+                            camera_->GetGPUProjection());
 
 
                         // Draw base (replace blend) batches first
                         // Draw base (replace blend) batches first
                         i->litBaseBatches_.Draw(this, camera_, false, false, allowDepthWrite);
                         i->litBaseBatches_.Draw(this, camera_, false, false, allowDepthWrite);

+ 4 - 2
Source/Urho3D/LuaScript/pkgs/Graphics/Camera.pkg

@@ -41,7 +41,8 @@ class Camera : public Component
     bool IsOrthographic() const;
     bool IsOrthographic() const;
     bool GetAutoAspectRatio() const;
     bool GetAutoAspectRatio() const;
     const Frustum& GetFrustum() const;
     const Frustum& GetFrustum() const;
-    const Matrix4& GetProjection() const;
+    Matrix4 GetProjection() const;
+    Matrix4 GetGPUProjection() const;
     const Matrix3x4& GetView() const;
     const Matrix3x4& GetView() const;
     void GetFrustumSize(Vector3& near, Vector3& far) const;
     void GetFrustumSize(Vector3& near, Vector3& far) const;
     float GetHalfViewSize() const;
     float GetHalfViewSize() const;
@@ -76,7 +77,8 @@ class Camera : public Component
     tolua_property__is_set bool orthographic;
     tolua_property__is_set bool orthographic;
     tolua_property__get_set bool autoAspectRatio;
     tolua_property__get_set bool autoAspectRatio;
     tolua_readonly tolua_property__get_set Frustum& frustum;
     tolua_readonly tolua_property__get_set Frustum& frustum;
-    tolua_readonly tolua_property__get_set Matrix4& projection;
+    tolua_readonly tolua_property__get_set Matrix4 projection;
+    tolua_readonly tolua_property__get_set Matrix4 GPUProjection;
     tolua_readonly tolua_property__get_set Matrix3x4& view;
     tolua_readonly tolua_property__get_set Matrix3x4& view;
     tolua_readonly tolua_property__get_set float halfViewSize;
     tolua_readonly tolua_property__get_set float halfViewSize;
     tolua_readonly tolua_property__get_set Frustum viewSpaceFrustum;
     tolua_readonly tolua_property__get_set Frustum viewSpaceFrustum;

+ 1 - 1
Source/Urho3D/UI/Text3D.cpp

@@ -713,7 +713,7 @@ void Text3D::CalculateFixedScreenSize(const FrameInfo& frame)
 
 
         if (!frame.camera_->IsOrthographic())
         if (!frame.camera_->IsOrthographic())
         {
         {
-            Matrix4 viewProj(frame.camera_->GetProjection(false) * frame.camera_->GetView());
+            Matrix4 viewProj(frame.camera_->GetProjection() * frame.camera_->GetView());
             Vector4 projPos(viewProj * Vector4(worldPosition, 1.0f));
             Vector4 projPos(viewProj * Vector4(worldPosition, 1.0f));
             worldScale *= textScaling * halfViewWorldSize * projPos.w_;
             worldScale *= textScaling * halfViewWorldSize * projPos.w_;
         }
         }