Browse Source

Merged the shaderData_ and worldTransform_ members of Batch & SourceBatch. The idea is that a batch can define multiple world transforms. For static geometry this means instance transforms. For skinned geometry they are bone transforms instead.
Inlined some functions in View & Drawable.

Lasse Öörni 12 years ago
parent
commit
c20257cdf7

+ 0 - 1
Docs/LuaScriptAPI.dox

@@ -404,7 +404,6 @@ section LuaScriptAPI_GlobalConstants Global constants
 - int SP_VERTEXLIGHTS
 - int SP_MATERIAL
 - int SP_OBJECTTRANSFORM
-- int SP_OBJECTDATA
 - int MAX_SHADER_PARAMETER_GROUPS
 - int LIGHT_DIRECTIONAL
 - int LIGHT_SPOT

+ 6 - 12
Source/Engine/Graphics/AnimatedModel.cpp

@@ -223,16 +223,10 @@ void AnimatedModel::UpdateBatches(const FrameInfo& frame)
     if (batches_.Size() > 1)
     {
         for (unsigned i = 0; i < batches_.Size(); ++i)
-        {
             batches_[i].distance_ = frame.camera_->GetDistance(worldTransform * geometryData_[i].center_);
-            batches_[i].worldTransform_ = &worldTransform;
-        }
     }
     else if (batches_.Size() == 1)
-    {
         batches_[0].distance_ = distance_;
-        batches_[0].worldTransform_ = &worldTransform;
-    }
 
     float scale = worldBoundingBox.Size().DotProduct(DOT_SCALE);
     float newLodDistance = frame.camera_->GetLodDistance(distance_, scale, lodBias_);
@@ -351,21 +345,21 @@ void AnimatedModel::SetModel(Model* model, bool createBones)
                 // Check if model has per-geometry bone mappings
                 if (geometrySkinMatrices_.Size() && geometrySkinMatrices_[i].Size())
                 {
-                    batches_[i].shaderData_ = geometrySkinMatrices_[i][0].Data();
-                    batches_[i].shaderDataSize_ = geometrySkinMatrices_[i].Size() * 12;
+                    batches_[i].worldTransform_ = &geometrySkinMatrices_[i][0];
+                    batches_[i].numWorldTransforms_ = geometrySkinMatrices_[i].Size();
                 }
                 // If not, use the global skin matrices
                 else
                 {
-                    batches_[i].shaderData_ = skinMatrices_[0].Data();
-                    batches_[i].shaderDataSize_ = skinMatrices_.Size() * 12;
+                    batches_[i].worldTransform_ = &skinMatrices_[0];
+                    batches_[i].numWorldTransforms_ = skinMatrices_.Size();
                 }
             }
             else
             {
                 batches_[i].geometryType_ = GEOM_STATIC;
-                batches_[i].shaderData_ = 0;
-                batches_[i].shaderDataSize_ = 0;
+                batches_[i].worldTransform_ = &node_->GetWorldTransform();
+                batches_[i].numWorldTransforms_ = 1;
             }
         }
     }

+ 11 - 7
Source/Engine/Graphics/Batch.cpp

@@ -288,13 +288,17 @@ void Batch::Prepare(View* view, bool setModelTransform) const
         graphics->SetShaderParameter(PSP_GBUFFERINVSIZE, Vector4(sizeX, sizeY, 0.0f, 0.0f));
     }
     
-    // Set model transform
+    // Set model or skinning transforms
     if (setModelTransform && graphics->NeedParameterUpdate(SP_OBJECTTRANSFORM, worldTransform_))
-        graphics->SetShaderParameter(VSP_MODEL, *worldTransform_);
-    
-    // Set skinning transforms
-    if (shaderData_ && shaderDataSize_ && graphics->NeedParameterUpdate(SP_OBJECTDATA, shaderData_))
-        graphics->SetShaderParameter(VSP_SKINMATRICES, shaderData_, shaderDataSize_);
+    {
+        if (geometryType_ == GEOM_SKINNED)
+        {
+            graphics->SetShaderParameter(VSP_SKINMATRICES, reinterpret_cast<const float*>(worldTransform_), 
+                12 * numWorldTransforms_);
+        }
+        else
+            graphics->SetShaderParameter(VSP_MODEL, *worldTransform_);
+    }
     
     // Set zone-related shader parameters
     BlendMode blend = graphics->GetBlendMode();
@@ -699,7 +703,7 @@ void BatchGroup::Draw(View* view) const
                     startIndex += instances;
                 }
             }
-            // Stream offset supported, and instancing buffer has been already filled, so just draw
+            // Stream offset supported and instancing buffer has been already filled, so just draw
             else
             {
                 graphics->SetIndexBuffer(geometry_->GetIndexBuffer());

+ 18 - 8
Source/Engine/Graphics/Batch.h

@@ -24,9 +24,9 @@
 
 #include "Drawable.h"
 #include "MathDefs.h"
+#include "Matrix3x4.h"
 #include "Ptr.h"
 #include "Rect.h"
-#include "Vector4.h"
 
 namespace Urho3D
 {
@@ -61,9 +61,8 @@ struct Batch
         geometry_(rhs.geometry_),
         material_(rhs.material_),
         worldTransform_(rhs.worldTransform_),
+        numWorldTransforms_(rhs.numWorldTransforms_),
         lightQueue_(0),
-        shaderData_(rhs.shaderData_),
-        shaderDataSize_(rhs.shaderDataSize_),
         geometryType_(rhs.geometryType_),
         overrideView_(rhs.overrideView_),
         isBase_(false)
@@ -85,8 +84,10 @@ struct Batch
     Geometry* geometry_;
     /// Material.
     Material* material_;
-    /// %Object's world transform.
+    /// World transform(s). For a skinned model, these are the bone transforms.
     const Matrix3x4* worldTransform_;
+    /// Number of world transforms.
+    unsigned numWorldTransforms_;
     /// Camera.
     Camera* camera_;
     /// Zone.
@@ -99,10 +100,6 @@ struct Batch
     ShaderVariation* vertexShader_;
     /// Pixel shader.
     ShaderVariation* pixelShader_;
-    /// Vertex shader data.
-    const float* shaderData_;
-    /// Vertex shader data size in floats.
-    unsigned shaderDataSize_;
     /// %Geometry type.
     GeometryType geometryType_;
     /// Override view transform flag.
@@ -155,6 +152,19 @@ struct BatchGroup : public Batch
     {
     }
     
+    /// Add world transform(s) from a batch.
+    void AddTransforms(const Batch& batch)
+    {
+        InstanceData newInstance;
+        newInstance.distance_ = batch.distance_;
+        
+        for (unsigned i = 0; i < batch.numWorldTransforms_; ++i)
+        {
+            newInstance.worldTransform_ = &batch.worldTransform_[i];
+            instances_.Push(newInstance);
+        }
+    }
+    
     /// Pre-set the instance transforms. Buffer must be big enough to hold all transforms.
     void SetTransforms(void* lockedData, unsigned& freeIndex);
     /// Prepare and draw.

+ 6 - 5
Source/Engine/Graphics/DecalSet.cpp

@@ -218,7 +218,8 @@ void DecalSet::UpdateBatches(const FrameInfo& frame)
     lodDistance_ = frame.camera_->GetLodDistance(distance_, scale, lodBias_);
     
     batches_[0].distance_ = distance_;
-    batches_[0].worldTransform_ = &worldTransform;
+    if (!skinned_)
+        batches_[0].worldTransform_ = &worldTransform;
 }
 
 void DecalSet::UpdateGeometry(const FrameInfo& frame)
@@ -1074,14 +1075,14 @@ void DecalSet::UpdateBatch()
     if (skinMatrices_.Size())
     {
         batches_[0].geometryType_ = GEOM_SKINNED;
-        batches_[0].shaderData_ = skinMatrices_[0].Data();
-        batches_[0].shaderDataSize_ = skinMatrices_.Size() * 12;
+        batches_[0].worldTransform_ = &skinMatrices_[0];
+        batches_[0].numWorldTransforms_ = skinMatrices_.Size();
     }
     else
     {
         batches_[0].geometryType_ = GEOM_STATIC;
-        batches_[0].shaderData_ = 0;
-        batches_[0].shaderDataSize_ = 0;
+        batches_[0].worldTransform_ = &node_->GetWorldTransform();
+        batches_[0].numWorldTransforms_ = 1;
     }
 }
 

+ 1 - 22
Source/Engine/Graphics/Drawable.cpp

@@ -43,8 +43,7 @@ SourceBatch::SourceBatch() :
     distance_(0.0f),
     geometry_(0),
     worldTransform_(&Matrix3x4::IDENTITY),
-    shaderData_(0),
-    shaderDataSize_(0),
+    numWorldTransforms_(1),
     geometryType_(GEOM_STATIC),
     overrideView_(false)
 {
@@ -289,26 +288,6 @@ void Drawable::MarkInView(const FrameInfo& frame, bool mainView)
     }
 }
 
-void Drawable::ClearLights()
-{
-    basePassFlags_ = 0;
-    firstLight_ = 0;
-    lights_.Clear();
-    vertexLights_.Clear();
-}
-
-void Drawable::AddLight(Light* light)
-{
-    if (lights_.Empty())
-        firstLight_ = light;
-    lights_.Push(light);
-}
-
-void Drawable::AddVertexLight(Light* light)
-{
-    vertexLights_.Push(light);
-}
-
 void Drawable::LimitLights()
 {
     // Maximum lights value 0 means unlimited

+ 26 - 11
Source/Engine/Graphics/Drawable.h

@@ -86,12 +86,10 @@ struct SourceBatch
     Geometry* geometry_;
     /// Material.
     SharedPtr<Material> material_;
-    /// %Object's world transform.
+    /// World transform(s). For a skinned model, these are the bone transforms.
     const Matrix3x4* worldTransform_;
-    /// Vertex shader data in floats.
-    const float* shaderData_;
-    /// Vertex shader data size.
-    unsigned shaderDataSize_;
+    /// Number of world transforms.
+    unsigned numWorldTransforms_;
     /// %Geometry type.
     GeometryType geometryType_;
     /// Override view transform flag.
@@ -200,12 +198,6 @@ public:
     void SetMinMaxZ(float minZ, float maxZ);
     /// Mark in view (either the main camera, or a shadow camera view) this frame.
     void MarkInView(const FrameInfo& frame, bool mainView = true);
-    /// Clear lights and base pass flags for a new frame.
-    void ClearLights();
-    /// Add a per-pixel light.
-    void AddLight(Light* light);
-    /// Add a per-vertex light.
-    void AddVertexLight(Light* light);
     /// Sort and limit per-pixel lights to maximum allowed. Convert extra lights into vertex lights.
     void LimitLights();
     /// Sort and limit per-vertex lights to maximum allowed.
@@ -243,6 +235,29 @@ public:
     /// Return the maximum view-space depth.
     float GetMaxZ() const { return maxZ_; }
     
+    // Clear the frame's light list.
+    void Drawable::ClearLights()
+    {
+        basePassFlags_ = 0;
+        firstLight_ = 0;
+        lights_.Clear();
+        vertexLights_.Clear();
+    }
+
+    // Add a per-pixel light affecting the object this frame.
+    void Drawable::AddLight(Light* light)
+    {
+        if (lights_.Empty())
+            firstLight_ = light;
+        lights_.Push(light);
+    }
+
+    // Add a per-vertex light affecting the object this frame.
+    void Drawable::AddVertexLight(Light* light)
+    {
+        vertexLights_.Push(light);
+    }
+
 protected:
     /// Handle node being assigned.
     virtual void OnNodeSet(Node* node);

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

@@ -291,7 +291,6 @@ enum ShaderParameterGroup
     SP_VERTEXLIGHTS,
     SP_MATERIAL,
     SP_OBJECTTRANSFORM,
-    SP_OBJECTDATA,
     MAX_SHADER_PARAMETER_GROUPS
 };
 

+ 11 - 41
Source/Engine/Graphics/View.cpp

@@ -43,7 +43,6 @@
 #include "VertexBuffer.h"
 #include "View.h"
 #include "WorkQueue.h"
-#include "Zone.h"
 
 #include "DebugNew.h"
 
@@ -917,6 +916,7 @@ void View::GetBatches()
                     Batch volumeBatch;
                     volumeBatch.geometry_ = renderer_->GetLightGeometry(light);
                     volumeBatch.worldTransform_ = &light->GetVolumeTransform(camera_);
+                    volumeBatch.numWorldTransforms_ = 1;
                     volumeBatch.overrideView_ = light->GetLightType() == LIGHT_DIRECTIONAL;
                     volumeBatch.camera_ = camera_;
                     volumeBatch.lightQueue_ = &lightQueue;
@@ -2312,32 +2312,6 @@ void View::FindZone(Drawable* drawable)
     drawable->SetZone(newZone, temporary);
 }
 
-Zone* View::GetZone(Drawable* drawable)
-{
-    if (cameraZoneOverride_)
-        return cameraZone_;
-    Zone* drawableZone = drawable->GetZone();
-    return drawableZone ? drawableZone : cameraZone_;
-}
-
-unsigned View::GetLightMask(Drawable* drawable)
-{
-    return drawable->GetLightMask() & GetZone(drawable)->GetLightMask();
-}
-
-unsigned View::GetShadowMask(Drawable* drawable)
-{
-    return drawable->GetShadowMask() & GetZone(drawable)->GetShadowMask();
-}
-
-unsigned long long View::GetVertexLightQueueHash(const PODVector<Light*>& vertexLights)
-{
-    unsigned long long hash = 0;
-    for (PODVector<Light*>::ConstIterator i = vertexLights.Begin(); i != vertexLights.End(); ++i)
-        hash += (unsigned long long)(*i);
-    return hash;
-}
-
 Technique* View::GetTechnique(Drawable* drawable, Material* material)
 {
     if (!material)
@@ -2414,8 +2388,7 @@ void View::AddBatchToQueue(BatchQueue& batchQueue, Batch& batch, Technique* tech
         batch.material_ = renderer_->GetDefaultMaterial();
     
     // Convert to instanced if possible
-    if (allowInstancing && batch.geometryType_ == GEOM_STATIC && batch.geometry_->GetIndexBuffer() && !batch.shaderData_ &&
-        !batch.overrideView_)
+    if (allowInstancing && batch.geometryType_ == GEOM_STATIC && batch.geometry_->GetIndexBuffer() && !batch.overrideView_)
         batch.geometryType_ = GEOM_INSTANCED;
     
     if (batch.geometryType_ == GEOM_INSTANCED)
@@ -2432,20 +2405,17 @@ void View::AddBatchToQueue(BatchQueue& batchQueue, Batch& batch, Technique* tech
             newGroup.geometryType_ = GEOM_STATIC;
             renderer_->SetBatchShaders(newGroup, tech, allowShadows);
             newGroup.CalculateSortKey();
-            newGroup.instances_.Push(InstanceData(batch.worldTransform_, batch.distance_));
-            groups->Insert(MakePair(key, newGroup));
+            i = groups->Insert(MakePair(key, newGroup));
         }
-        else
+
+        int oldSize = i->second_.instances_.Size();
+        i->second_.AddTransforms(batch);
+        // Convert to using instancing shaders when the instancing limit is reached
+        if (oldSize < minInstances_ && (int)i->second_.instances_.Size() >= minInstances_)
         {
-            i->second_.instances_.Push(InstanceData(batch.worldTransform_, batch.distance_));
-            
-            // Convert to using instancing shaders when the instancing limit is reached
-            if (i->second_.instances_.Size() == minInstances_)
-            {
-                i->second_.geometryType_ = GEOM_INSTANCED;
-                renderer_->SetBatchShaders(i->second_, tech, allowShadows);
-                i->second_.CalculateSortKey();
-            }
+            i->second_.geometryType_ = GEOM_INSTANCED;
+            renderer_->SetBatchShaders(i->second_, tech, allowShadows);
+            i->second_.CalculateSortKey();
         }
     }
     else

+ 31 - 8
Source/Engine/Graphics/View.h

@@ -27,6 +27,7 @@
 #include "List.h"
 #include "Object.h"
 #include "Polyhedron.h"
+#include "Zone.h"
 
 namespace Urho3D
 {
@@ -190,14 +191,6 @@ private:
     IntRect GetShadowMapViewport(Light* light, unsigned splitIndex, Texture2D* shadowMap);
     /// Find and set a new zone for a drawable when it has moved.
     void FindZone(Drawable* drawable);
-    /// Return the drawable's zone, or camera zone if it has override mode enabled.
-    Zone* GetZone(Drawable* drawable);
-    /// Return the drawable's light mask, considering also its zone.
-    unsigned GetLightMask(Drawable* drawable);
-    /// Return the drawable's shadow mask, considering also its zone.
-    unsigned GetShadowMask(Drawable* drawable);
-    /// Return hash code for a vertex light queue.
-    unsigned long long GetVertexLightQueueHash(const PODVector<Light*>& vertexLights);
     /// Return material technique, considering the drawable's LOD distance.
     Technique* GetTechnique(Drawable* drawable, Material* material);
     /// Check if material should render an auxiliary view (if it has a camera attached.)
@@ -213,6 +206,36 @@ private:
     /// Return the proper depth-stencil surface to use for a rendertarget.
     RenderSurface* GetDepthStencil(RenderSurface* renderTarget);
     
+    /// Return the drawable's zone, or camera zone if it has override mode enabled.
+    Zone* GetZone(Drawable* drawable)
+    {
+        if (cameraZoneOverride_)
+            return cameraZone_;
+        Zone* drawableZone = drawable->GetZone();
+        return drawableZone ? drawableZone : cameraZone_;
+    }
+
+    /// Return the drawable's light mask, considering also its zone.
+    unsigned GetLightMask(Drawable* drawable)
+    {
+        return drawable->GetLightMask() & GetZone(drawable)->GetLightMask();
+    }
+
+    /// Return the drawable's shadow mask, considering also its zone.
+    unsigned GetShadowMask(Drawable* drawable)
+    {
+        return drawable->GetShadowMask() & GetZone(drawable)->GetShadowMask();
+    }
+
+    /// Return hash code for a vertex light queue.
+    unsigned long long GetVertexLightQueueHash(const PODVector<Light*>& vertexLights)
+    {
+        unsigned long long hash = 0;
+        for (PODVector<Light*>::ConstIterator i = vertexLights.Begin(); i != vertexLights.End(); ++i)
+            hash += (unsigned long long)(*i);
+        return hash;
+    }
+
     /// Graphics subsystem.
     WeakPtr<Graphics> graphics_;
     /// Renderer subsystem.

+ 0 - 1
Source/Extras/LuaScript/pkgs/Graphics/GraphicsDefs.pkg

@@ -187,7 +187,6 @@ enum ShaderParameterGroup
     SP_VERTEXLIGHTS,
     SP_MATERIAL,
     SP_OBJECTTRANSFORM,
-    SP_OBJECTDATA,
     MAX_SHADER_PARAMETER_GROUPS
 };