Browse Source

Zone system refactoring. Now objects check which zone they're in, for per-object ambient light and fog settings.

Lasse Öörni 14 years ago
parent
commit
00cca6b83c

+ 2 - 6
Engine/Graphics/AnimatedModel.cpp

@@ -723,14 +723,10 @@ void AnimatedModel::OnNodeSet(Node* node)
 
 
 void AnimatedModel::OnMarkedDirty(Node* node)
 void AnimatedModel::OnMarkedDirty(Node* node)
 {
 {
+    Drawable::OnMarkedDirty(node);
+    
     // If the scene node or any of the bone nodes move, mark skinning dirty
     // If the scene node or any of the bone nodes move, mark skinning dirty
     skinningDirty_ = true;
     skinningDirty_ = true;
-    if (node == node_)
-    {
-        worldBoundingBoxDirty_ = true;
-        if (octant_)
-            octant_->GetRoot()->QueueReinsertion(this);
-    }
 }
 }
 
 
 void AnimatedModel::OnWorldBoundingBoxUpdate()
 void AnimatedModel::OnWorldBoundingBoxUpdate()

+ 1 - 1
Engine/Graphics/AnimatedModel.h

@@ -48,7 +48,7 @@ public:
     
     
     /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update.
     /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update.
     virtual void ApplyAttributes();
     virtual void ApplyAttributes();
-    /// Process renderer raycast.
+    /// Process octree raycast.
     virtual void ProcessRayQuery(RayOctreeQuery& query, float initialDistance);
     virtual void ProcessRayQuery(RayOctreeQuery& query, float initialDistance);
     /// Update before octree reinsertion. Animation is updated here.
     /// Update before octree reinsertion. Animation is updated here.
     virtual void Update(const FrameInfo& frame);
     virtual void Update(const FrameInfo& frame);

+ 55 - 14
Engine/Graphics/Batch.cpp

@@ -35,6 +35,7 @@
 #include "Technique.h"
 #include "Technique.h"
 #include "Texture2D.h"
 #include "Texture2D.h"
 #include "VertexBuffer.h"
 #include "VertexBuffer.h"
+#include "Zone.h"
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
 
 
@@ -76,7 +77,7 @@ void Batch::CalculateSortKey()
         (((unsigned long long)material) << 16) | geometry;
         (((unsigned long long)material) << 16) | geometry;
 }
 }
 
 
-void Batch::Prepare(Graphics* graphics, Renderer* renderer, const HashMap<StringHash, Vector4>& shaderParameters, bool setModelTransform) const
+void Batch::Prepare(Graphics* graphics, Renderer* renderer, bool setModelTransform) const
 {
 {
     if (!vertexShader_ || !pixelShader_)
     if (!vertexShader_ || !pixelShader_)
         return;
         return;
@@ -98,13 +99,6 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, const HashMap<String
     // Set shaders
     // Set shaders
     graphics->SetShaders(vertexShader_, pixelShader_);
     graphics->SetShaders(vertexShader_, pixelShader_);
     
     
-    // Set global shader parameters
-    for (HashMap<StringHash, Vector4>::ConstIterator i = shaderParameters.Begin(); i != shaderParameters.End(); ++i)
-    {
-        if (graphics->NeedParameterUpdate(i->first_, &shaderParameters))
-            graphics->SetShaderParameter(i->first_, i->second_);
-    }
-    
     // Set viewport and camera shader parameters
     // Set viewport and camera shader parameters
     if (graphics->NeedParameterUpdate(VSP_CAMERAPOS, camera_))
     if (graphics->NeedParameterUpdate(VSP_CAMERAPOS, camera_))
         graphics->SetShaderParameter(VSP_CAMERAPOS, camera_->GetWorldPosition());
         graphics->SetShaderParameter(VSP_CAMERAPOS, camera_->GetWorldPosition());
@@ -112,6 +106,25 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, const HashMap<String
     if (graphics->NeedParameterUpdate(VSP_CAMERAROT, camera_))
     if (graphics->NeedParameterUpdate(VSP_CAMERAROT, camera_))
         graphics->SetShaderParameter(VSP_CAMERAROT, camera_->GetWorldTransform().RotationMatrix());
         graphics->SetShaderParameter(VSP_CAMERAROT, camera_->GetWorldTransform().RotationMatrix());
     
     
+    if (graphics->NeedParameterUpdate(VSP_DEPTHMODE, camera_))
+    {
+        Vector4 depthMode = Vector4::ZERO;
+        if (camera_->IsOrthographic())
+        {
+            depthMode.x_ = 1.0f;
+            #ifdef USE_OPENGL
+            depthMode.z_ = 0.5f;
+            depthMode.w_ = 0.5f;
+            #else
+            depthMode.z_ = 1.0f;
+            #endif
+        }
+        else
+            depthMode.w_ = 1.0f / camera_->GetFarClip();
+        
+        graphics->SetShaderParameter(VSP_DEPTHMODE, depthMode);
+    }
+
     if (overrideView_)
     if (overrideView_)
     {
     {
         if (graphics->NeedParameterUpdate(VSP_VIEWPROJ, ((unsigned char*)camera_) + 4))
         if (graphics->NeedParameterUpdate(VSP_VIEWPROJ, ((unsigned char*)camera_) + 4))
@@ -141,6 +154,30 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, const HashMap<String
             graphics->SetShaderParameter(VSP_SKINMATRICES, shaderData_, shaderDataSize_);
             graphics->SetShaderParameter(VSP_SKINMATRICES, shaderData_, shaderDataSize_);
     }
     }
     
     
+    // Set zone-related shader parameters
+    if (zone_)
+    {
+        if (graphics->NeedParameterUpdate(PSP_AMBIENTCOLOR, zone_))
+            graphics->SetShaderParameter(PSP_AMBIENTCOLOR, zone_->GetAmbientColor().ToVector4());
+        
+        if (graphics->NeedParameterUpdate(PSP_FOGCOLOR, zone_))
+            graphics->SetShaderParameter(PSP_FOGCOLOR, zone_->GetFogColor().ToVector4());
+        
+        if (graphics->NeedParameterUpdate(PSP_FOGPARAMS, zone_))
+        {
+            float farClip = camera_->GetFarClip();
+            float nearClip = camera_->GetNearClip();
+            float fogStart = Min(zone_->GetFogStart(), farClip);
+            float fogEnd = Min(zone_->GetFogEnd(), farClip);
+            if (fogStart >= fogEnd * (1.0f - M_LARGE_EPSILON))
+                fogStart = fogEnd * (1.0f - M_LARGE_EPSILON);
+            float fogRange = Max(fogEnd - fogStart, M_EPSILON);
+            Vector4 fogParams(fogStart / farClip, fogEnd / farClip, farClip / fogRange, 0.0f);
+            
+            graphics->SetShaderParameter(PSP_FOGPARAMS, fogParams);
+        }
+    }
+    
     // Set light-related shader parameters
     // Set light-related shader parameters
     Light* light = 0;
     Light* light = 0;
     Texture2D* shadowMap = 0;
     Texture2D* shadowMap = 0;
@@ -413,9 +450,9 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, const HashMap<String
     }
     }
 }
 }
 
 
-void Batch::Draw(Graphics* graphics, Renderer* renderer, const HashMap<StringHash, Vector4>& shaderParameters) const
+void Batch::Draw(Graphics* graphics, Renderer* renderer) const
 {
 {
-    Prepare(graphics, renderer, shaderParameters);
+    Prepare(graphics, renderer);
     geometry_->Draw(graphics);
     geometry_->Draw(graphics);
 }
 }
 
 
@@ -437,12 +474,13 @@ void BatchGroup::SetTransforms(Renderer* renderer, void* lockedData, unsigned& f
     freeIndex += instances_.Size();
     freeIndex += instances_.Size();
 }
 }
 
 
-void BatchGroup::Draw(Graphics* graphics, Renderer* renderer, const HashMap<StringHash, Vector4>& shaderParameters) const
+void BatchGroup::Draw(Graphics* graphics, Renderer* renderer) const
 {
 {
     if (!instances_.Size())
     if (!instances_.Size())
         return;
         return;
     
     
     // Construct a temporary batch for rendering
     // Construct a temporary batch for rendering
+    /// \todo BatchGroup could subclass Batch to avoid this
     Batch batch;
     Batch batch;
     batch.geometry_ = geometry_;
     batch.geometry_ = geometry_;
     batch.material_ = material_;
     batch.material_ = material_;
@@ -450,6 +488,7 @@ void BatchGroup::Draw(Graphics* graphics, Renderer* renderer, const HashMap<Stri
     batch.vertexShader_ = vertexShader_;
     batch.vertexShader_ = vertexShader_;
     batch.pixelShader_ = pixelShader_;
     batch.pixelShader_ = pixelShader_;
     batch.camera_ = camera_;
     batch.camera_ = camera_;
+    batch.zone_ = zone_;
     batch.lightQueue_ = lightQueue_;
     batch.lightQueue_ = lightQueue_;
     batch.vertexShaderIndex_ = vertexShaderIndex_;
     batch.vertexShaderIndex_ = vertexShaderIndex_;
     
     
@@ -460,7 +499,7 @@ void BatchGroup::Draw(Graphics* graphics, Renderer* renderer, const HashMap<Stri
     VertexBuffer* instanceBuffer = renderer->GetInstancingBuffer();
     VertexBuffer* instanceBuffer = renderer->GetInstancingBuffer();
     if (!instanceBuffer || instances_.Size() < minGroupSize || geometry_->GetIndexCount() > maxIndexCount)
     if (!instanceBuffer || instances_.Size() < minGroupSize || geometry_->GetIndexCount() > maxIndexCount)
     {
     {
-        batch.Prepare(graphics, renderer, shaderParameters, false);
+        batch.Prepare(graphics, renderer, false);
         
         
         graphics->SetIndexBuffer(geometry_->GetIndexBuffer());
         graphics->SetIndexBuffer(geometry_->GetIndexBuffer());
         graphics->SetVertexBuffers(geometry_->GetVertexBuffers(), geometry_->GetVertexElementMasks());
         graphics->SetVertexBuffers(geometry_->GetVertexBuffers(), geometry_->GetVertexElementMasks());
@@ -486,7 +525,7 @@ void BatchGroup::Draw(Graphics* graphics, Renderer* renderer, const HashMap<Stri
         else
         else
             batch.vertexShader_ = vertexShaders[vertexShaderIndex_ + GEOM_INSTANCED];
             batch.vertexShader_ = vertexShaders[vertexShaderIndex_ + GEOM_INSTANCED];
         
         
-        batch.Prepare(graphics, renderer, shaderParameters, false);
+        batch.Prepare(graphics, renderer, false);
         
         
         // Get the geometry vertex buffers, then add the instancing stream buffer
         // Get the geometry vertex buffers, then add the instancing stream buffer
         // Hack: use a const_cast to avoid dynamic allocation of new temp vectors
         // Hack: use a const_cast to avoid dynamic allocation of new temp vectors
@@ -560,6 +599,7 @@ void BatchQueue::AddBatch(const Batch& batch, bool instancing)
     else
     else
     {
     {
         BatchGroupKey key;
         BatchGroupKey key;
+        key.zone_ = batch.zone_;
         key.lightQueue_ = batch.lightQueue_;
         key.lightQueue_ = batch.lightQueue_;
         key.pass_ = batch.pass_;
         key.pass_ = batch.pass_;
         key.material_ = batch.material_;
         key.material_ = batch.material_;
@@ -570,7 +610,7 @@ void BatchQueue::AddBatch(const Batch& batch, bool instancing)
         Map<BatchGroupKey, BatchGroup>::Iterator i = groups->Find(key);
         Map<BatchGroupKey, BatchGroup>::Iterator i = groups->Find(key);
         if (i == groups->End())
         if (i == groups->End())
         {
         {
-            // Create new group
+            // Create a new group
             BatchGroup newGroup;
             BatchGroup newGroup;
             newGroup.geometry_ = batch.geometry_;
             newGroup.geometry_ = batch.geometry_;
             newGroup.material_ = batch.material_;
             newGroup.material_ = batch.material_;
@@ -578,6 +618,7 @@ void BatchQueue::AddBatch(const Batch& batch, bool instancing)
             newGroup.vertexShader_ = batch.vertexShader_;
             newGroup.vertexShader_ = batch.vertexShader_;
             newGroup.pixelShader_ = batch.pixelShader_;
             newGroup.pixelShader_ = batch.pixelShader_;
             newGroup.camera_ = batch.camera_;
             newGroup.camera_ = batch.camera_;
+            newGroup.zone_ = batch.zone_;
             newGroup.lightQueue_ = batch.lightQueue_;
             newGroup.lightQueue_ = batch.lightQueue_;
             newGroup.vertexShaderIndex_ = batch.vertexShaderIndex_;
             newGroup.vertexShaderIndex_ = batch.vertexShaderIndex_;
             newGroup.instances_.Push(InstanceData(batch.worldTransform_, batch.distance_));
             newGroup.instances_.Push(InstanceData(batch.worldTransform_, batch.distance_));

+ 37 - 19
Engine/Graphics/Batch.h

@@ -43,6 +43,7 @@ class Renderer;
 class ShaderVariation;
 class ShaderVariation;
 class Texture2D;
 class Texture2D;
 class VertexBuffer;
 class VertexBuffer;
+class Zone;
 struct LightBatchQueue;
 struct LightBatchQueue;
 
 
 /// Description of a 3D geometry draw call.
 /// Description of a 3D geometry draw call.
@@ -50,6 +51,7 @@ struct Batch
 {
 {
     /// Construct with defaults.
     /// Construct with defaults.
     Batch() :
     Batch() :
+        zone_(0),
         lightQueue_(0),
         lightQueue_(0),
         shaderData_(0),
         shaderData_(0),
         shaderDataSize_(0),
         shaderDataSize_(0),
@@ -62,9 +64,9 @@ struct Batch
     /// Calculate sort key, which consists of priority flag, light, pass and geometry.
     /// Calculate sort key, which consists of priority flag, light, pass and geometry.
     void CalculateSortKey();
     void CalculateSortKey();
     /// Prepare for rendering.
     /// Prepare for rendering.
-    void Prepare(Graphics* graphics, Renderer* renderer, const HashMap<StringHash, Vector4>& shaderParameters, bool setModelTransform = true) const;
+    void Prepare(Graphics* graphics, Renderer* renderer, bool setModelTransform = true) const;
     /// Prepare and draw.
     /// Prepare and draw.
-    void Draw(Graphics* graphics, Renderer* renderer, const HashMap<StringHash, Vector4>& shaderParameters) const;
+    void Draw(Graphics* graphics, Renderer* renderer) const;
     
     
     /// Geometry.
     /// Geometry.
     Geometry* geometry_;
     Geometry* geometry_;
@@ -72,6 +74,8 @@ struct Batch
     const Matrix3x4* worldTransform_;
     const Matrix3x4* worldTransform_;
     /// Camera.
     /// Camera.
     Camera* camera_;
     Camera* camera_;
+    /// Zone.
+    Zone* zone_;
     /// Light properties.
     /// Light properties.
     LightBatchQueue* lightQueue_;
     LightBatchQueue* lightQueue_;
     /// Material.
     /// Material.
@@ -138,7 +142,7 @@ struct BatchGroup
     /// Pre-set the instance transforms. Buffer must be big enough to hold all transforms.
     /// Pre-set the instance transforms. Buffer must be big enough to hold all transforms.
     void SetTransforms(Renderer* renderer, void* lockedData, unsigned& freeIndex);
     void SetTransforms(Renderer* renderer, void* lockedData, unsigned& freeIndex);
     /// Prepare and draw.
     /// Prepare and draw.
-    void Draw(Graphics* graphics, Renderer* renderer, const HashMap<StringHash, Vector4>& shaderParameters) const;
+    void Draw(Graphics* graphics, Renderer* renderer) const;
     
     
     /// Geometry.
     /// Geometry.
     Geometry* geometry_;
     Geometry* geometry_;
@@ -146,6 +150,8 @@ struct BatchGroup
     PODVector<InstanceData> instances_;
     PODVector<InstanceData> instances_;
     /// Camera.
     /// Camera.
     Camera* camera_;
     Camera* camera_;
+    /// Zone.
+    Zone* zone_;
     /// Light properties.
     /// Light properties.
     LightBatchQueue* lightQueue_;
     LightBatchQueue* lightQueue_;
     /// Material.
     /// Material.
@@ -165,6 +171,8 @@ struct BatchGroup
 /// Instanced draw call key.
 /// Instanced draw call key.
 struct BatchGroupKey
 struct BatchGroupKey
 {
 {
+    /// Zone.
+    Zone* zone_;
     /// Light properties.
     /// Light properties.
     LightBatchQueue* lightQueue_;
     LightBatchQueue* lightQueue_;
     /// Material pass.
     /// Material pass.
@@ -175,46 +183,56 @@ struct BatchGroupKey
     Geometry* geometry_;
     Geometry* geometry_;
     
     
     /// Test for equality with another batch group key.
     /// Test for equality with another batch group key.
-    bool operator == (const BatchGroupKey& rhs) const { return lightQueue_ == rhs.lightQueue_ && pass_ == rhs.pass_ && material_ == rhs.material_ && geometry_ == rhs.geometry_; }
+    bool operator == (const BatchGroupKey& rhs) const { return zone_ == rhs.zone_ && lightQueue_ == rhs.lightQueue_ && pass_ == rhs.pass_ && material_ == rhs.material_ && geometry_ == rhs.geometry_; }
     /// Test for inequality with another batch group key.
     /// Test for inequality with another batch group key.
-    bool operator != (const BatchGroupKey& rhs) const { return lightQueue_ != rhs.lightQueue_ || pass_ != rhs.pass_ || material_ != rhs.material_ || geometry_ != rhs.geometry_; }
+    bool operator != (const BatchGroupKey& rhs) const { return zone_ != rhs.zone_ || lightQueue_ != rhs.lightQueue_ || pass_ != rhs.pass_ || material_ != rhs.material_ || geometry_ != rhs.geometry_; }
     
     
     /// Test if less than another batch group key.
     /// Test if less than another batch group key.
     bool operator < (const BatchGroupKey& rhs) const
     bool operator < (const BatchGroupKey& rhs) const
     {
     {
-        if (lightQueue_ == rhs.lightQueue_)
+        if (zone_ == rhs.zone_)
         {
         {
-            if (pass_ == rhs.pass_)
+            if (lightQueue_ == rhs.lightQueue_)
             {
             {
-                if (material_ == rhs.material_)
-                    return geometry_ < rhs.geometry_;
+                if (pass_ == rhs.pass_)
+                {
+                    if (material_ == rhs.material_)
+                        return geometry_ < rhs.geometry_;
+                    else
+                        return material_ < rhs.material_;
+                }
                 else
                 else
-                    return material_ < rhs.material_;
+                    return pass_ < rhs.pass_;
             }
             }
             else
             else
-                return pass_ < rhs.pass_;
+                return lightQueue_ < rhs.lightQueue_;
         }
         }
         else
         else
-            return lightQueue_ < rhs.lightQueue_;
+            return zone_ < rhs.zone_;
     }
     }
     
     
     /// Test if greater than another batch group key.
     /// Test if greater than another batch group key.
     bool operator > (const BatchGroupKey& rhs) const
     bool operator > (const BatchGroupKey& rhs) const
     {
     {
-        if (lightQueue_ == rhs.lightQueue_)
+        if (zone_ == rhs.zone_)
         {
         {
-            if (pass_ == rhs.pass_)
+            if (lightQueue_ == rhs.lightQueue_)
             {
             {
-                if (material_ == rhs.material_)
-                    return geometry_ > rhs.geometry_;
+                if (pass_ == rhs.pass_)
+                {
+                    if (material_ == rhs.material_)
+                        return geometry_ > rhs.geometry_;
+                    else
+                        return material_ > rhs.material_;
+                }
                 else
                 else
-                    return material_ > rhs.material_;
+                    return pass_ > rhs.pass_;
             }
             }
             else
             else
-                return pass_ > rhs.pass_;
+                return lightQueue_ > rhs.lightQueue_;
         }
         }
         else
         else
-            return lightQueue_ > rhs.lightQueue_;
+            return zone_ > rhs.zone_;
     }
     }
 };
 };
 
 

+ 4 - 6
Engine/Graphics/BillboardSet.cpp

@@ -290,12 +290,10 @@ const PODVector<unsigned char>& BillboardSet::GetNetBillboardsAttr() const
 
 
 void BillboardSet::OnMarkedDirty(Node* node)
 void BillboardSet::OnMarkedDirty(Node* node)
 {
 {
-    if (node == node_)
-    {
-        Drawable::OnMarkedDirty(node);
-        if (relative_)
-            bufferDirty_ = true;
-    }
+    Drawable::OnMarkedDirty(node);
+    
+    if (node == node_ && relative_)
+        bufferDirty_ = true;
 }
 }
 
 
 void BillboardSet::OnWorldBoundingBoxUpdate()
 void BillboardSet::OnWorldBoundingBoxUpdate()

+ 55 - 5
Engine/Graphics/Drawable.cpp

@@ -29,6 +29,7 @@
 #include "Octree.h"
 #include "Octree.h"
 #include "OctreeQuery.h"
 #include "OctreeQuery.h"
 #include "Scene.h"
 #include "Scene.h"
+#include "Zone.h"
 
 
 #include "Sort.h"
 #include "Sort.h"
 
 
@@ -165,6 +166,54 @@ const BoundingBox& Drawable::GetWorldBoundingBox()
     return worldBoundingBox_;
     return worldBoundingBox_;
 }
 }
 
 
+void Drawable::FindZone(PODVector<Drawable*>& result)
+{
+    // First check if the last zones are still valid, to avoid making a new octree query
+    /// \todo Add zone mask to be able to exclude zones
+    Vector3 center = GetWorldBoundingBox().Center();
+    int bestPriority = M_MIN_INT;
+    Zone* newZone = 0;
+    for (Vector<WeakPtr<Zone> >::Iterator i = lastZones_.Begin(); i != lastZones_.End(); ++i)
+    {
+        Zone* zone = (*i);
+        int priority = zone->GetPriority();
+        if (zone && zone->IsInside(center) && priority > bestPriority)
+        {
+            newZone = zone;
+            bestPriority = priority;
+        }
+    }
+    
+    if (!newZone)
+    {
+        Octree* octree = octant_->GetRoot();
+        PointOctreeQuery query(result, center, DRAWABLE_ZONE);
+        octree->GetDrawables(query);
+        
+        // Store the zone query result for next time
+        lastZones_.Clear();
+        PODVector<Zone*>& zoneResult = reinterpret_cast<PODVector<Zone*>&>(result);
+        for (PODVector<Zone*>::Iterator i = zoneResult.Begin(); i != zoneResult.End(); ++i)
+        {
+            Zone* zone = (*i);
+            int priority = zone->GetPriority();
+            if (zone->IsInside(center) && priority > bestPriority)
+            {
+                newZone = zone;
+                bestPriority = priority;
+            }
+            lastZones_.Push(WeakPtr<Zone>(*i));
+        }
+    }
+    
+    zone_ = newZone;
+}
+
+void Drawable::SetSortValue(float value)
+{
+    sortValue_ = value;
+}
+
 void Drawable::MarkInView(const FrameInfo& frame)
 void Drawable::MarkInView(const FrameInfo& frame)
 {
 {
     viewFrameNumber_ = frame.frameNumber_;
     viewFrameNumber_ = frame.frameNumber_;
@@ -180,11 +229,6 @@ void Drawable::MarkInShadowView(const FrameInfo& frame)
     }
     }
 }
 }
 
 
-void Drawable::SetSortValue(float value)
-{
-    sortValue_ = value;
-}
-
 void Drawable::ClearLights()
 void Drawable::ClearLights()
 {
 {
     for (unsigned i = 0; i < basePassFlags_.Size(); ++i)
     for (unsigned i = 0; i < basePassFlags_.Size(); ++i)
@@ -229,6 +273,11 @@ void Drawable::SetBasePass(unsigned batchIndex)
     basePassFlags_[index] |= (1 << (batchIndex & 31));
     basePassFlags_[index] |= (1 << (batchIndex & 31));
 }
 }
 
 
+Zone* Drawable::GetZone() const
+{
+    return zone_;
+}
+
 bool Drawable::IsInView(unsigned frameNumber) const
 bool Drawable::IsInView(unsigned frameNumber) const
 {
 {
     return viewFrameNumber_ == frameNumber;
     return viewFrameNumber_ == frameNumber;
@@ -265,6 +314,7 @@ void Drawable::OnMarkedDirty(Node* node)
     if (node == node_)
     if (node == node_)
     {
     {
         worldBoundingBoxDirty_ = true;
         worldBoundingBoxDirty_ = true;
+        zone_.Reset();
         if (octant_)
         if (octant_)
             octant_->GetRoot()->QueueReinsertion(this);
             octant_->GetRoot()->QueueReinsertion(this);
     }
     }

+ 14 - 5
Engine/Graphics/Drawable.h

@@ -44,6 +44,7 @@ class Material;
 class OcclusionBuffer;
 class OcclusionBuffer;
 class Octant;
 class Octant;
 class RayOctreeQuery;
 class RayOctreeQuery;
+class Zone;
 
 
 /// Rendering frame update parameters.
 /// Rendering frame update parameters.
 struct FrameInfo
 struct FrameInfo
@@ -134,13 +135,13 @@ public:
     /// Return occlusion flag.
     /// Return occlusion flag.
     bool IsOccluder() const { return occluder_; }
     bool IsOccluder() const { return occluder_; }
     
     
-    /// Return octree octant.
-    Octant* GetOctant() const { return octant_; }
-    /// %Set sorting value. Called by View.
+    /// Find new zone from the octree.
+    void FindZone(PODVector<Drawable*>& result);
+    /// %Set sorting value.
     void SetSortValue(float value);
     void SetSortValue(float value);
-    /// Mark in view this frame. Called by View.
+    /// Mark in view this frame.
     void MarkInView(const FrameInfo& frame);
     void MarkInView(const FrameInfo& frame);
-    /// Mark in a shadow camera view this frame. If an actual view is already set, does not override it. Called by View.
+    /// Mark in a shadow camera view this frame. If an actual view is already set, does not override it.
     void MarkInShadowView(const FrameInfo& frame);
     void MarkInShadowView(const FrameInfo& frame);
     /// Clear lights and base pass flags for a new frame.
     /// Clear lights and base pass flags for a new frame.
     void ClearLights();
     void ClearLights();
@@ -150,6 +151,10 @@ public:
     void LimitLights();
     void LimitLights();
     /// %Set base pass flag for a batch.
     /// %Set base pass flag for a batch.
     void SetBasePass(unsigned batchIndex);
     void SetBasePass(unsigned batchIndex);
+    /// Return octree octant.
+    Octant* GetOctant() const { return octant_; }
+    /// Return current zone.
+    Zone* GetZone() const;
     /// Return distance from camera.
     /// Return distance from camera.
     float GetDistance() const { return distance_; }
     float GetDistance() const { return distance_; }
     /// Return LOD scaled distance from camera.
     /// Return LOD scaled distance from camera.
@@ -183,6 +188,10 @@ protected:
     
     
     /// Octree octant.
     /// Octree octant.
     Octant* octant_;
     Octant* octant_;
+    /// Current zone.
+    WeakPtr<Zone> zone_;
+    /// Last found zones.
+    Vector<WeakPtr<Zone> > lastZones_;
     /// World bounding box.
     /// World bounding box.
     BoundingBox worldBoundingBox_;
     BoundingBox worldBoundingBox_;
     /// Draw distance.
     /// Draw distance.

+ 1 - 1
Engine/Graphics/Light.h

@@ -158,7 +158,7 @@ public:
     
     
     /// Handle attribute change.
     /// Handle attribute change.
     virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
     virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
-    /// Process renderer raycast.
+    /// Process octree raycast.
     virtual void ProcessRayQuery(RayOctreeQuery& query, float initialDistance);
     virtual void ProcessRayQuery(RayOctreeQuery& query, float initialDistance);
     /// Calculate distance for rendering.
     /// Calculate distance for rendering.
     virtual void UpdateDistance(const FrameInfo& frame);
     virtual void UpdateDistance(const FrameInfo& frame);

+ 5 - 0
Engine/Graphics/Skybox.cpp

@@ -45,6 +45,11 @@ void Skybox::RegisterObject(Context* context)
     COPY_BASE_ATTRIBUTES(Skybox, StaticModel);
     COPY_BASE_ATTRIBUTES(Skybox, StaticModel);
 }
 }
 
 
+void Skybox::ProcessRayQuery(RayOctreeQuery& query, float initialDistance)
+{
+    // Return no ray hits, as camera rays practically always originate within the bounding box, blocking any other results
+}
+
 void Skybox::UpdateDistance(const FrameInfo& frame)
 void Skybox::UpdateDistance(const FrameInfo& frame)
 {
 {
     distance_ = 0.0f;
     distance_ = 0.0f;

+ 2 - 0
Engine/Graphics/Skybox.h

@@ -38,6 +38,8 @@ public:
     /// Register object factory. StaticModel must be registered first.
     /// Register object factory. StaticModel must be registered first.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
+    /// Process octree raycast.
+    void ProcessRayQuery(RayOctreeQuery& query, float initialDistance);
     /// Calculate distance for rendering.
     /// Calculate distance for rendering.
     virtual void UpdateDistance(const FrameInfo& frame);
     virtual void UpdateDistance(const FrameInfo& frame);
     /// Return rendering batch with distance, geometry, material and world transform filled.
     /// Return rendering batch with distance, geometry, material and world transform filled.

+ 1 - 1
Engine/Graphics/StaticModel.h

@@ -40,7 +40,7 @@ public:
     /// Register object factory. Drawable must be registered first.
     /// Register object factory. Drawable must be registered first.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Process renderer raycast.
+    /// Process octree raycast.
     virtual void ProcessRayQuery(RayOctreeQuery& query, float initialDistance);
     virtual void ProcessRayQuery(RayOctreeQuery& query, float initialDistance);
     /// Prepare geometry for rendering.
     /// Prepare geometry for rendering.
     virtual void UpdateGeometry(const FrameInfo& frame);
     virtual void UpdateGeometry(const FrameInfo& frame);

+ 63 - 74
Engine/Graphics/View.cpp

@@ -64,7 +64,7 @@ View::View(Context* context) :
     renderer_(GetSubsystem<Renderer>()),
     renderer_(GetSubsystem<Renderer>()),
     octree_(0),
     octree_(0),
     camera_(0),
     camera_(0),
-    zone_(0),
+    cameraZone_(0),
     renderTarget_(0),
     renderTarget_(0),
     depthStencil_(0)
     depthStencil_(0)
 {
 {
@@ -97,8 +97,6 @@ bool View::Define(RenderSurface* renderTarget, const Viewport& viewport)
     else
     else
         depthStencil_ = renderTarget->GetLinkedDepthBuffer();
         depthStencil_ = renderTarget->GetLinkedDepthBuffer();
     
     
-    zone_ = renderer_->GetDefaultZone();
-    
     // Validate the rect and calculate size. If zero rect, use whole render target size
     // Validate the rect and calculate size. If zero rect, use whole render target size
     int rtWidth = renderTarget ? renderTarget->GetWidth() : graphics_->GetWidth();
     int rtWidth = renderTarget ? renderTarget->GetWidth() : graphics_->GetWidth();
     int rtHeight = renderTarget ? renderTarget->GetHeight() : graphics_->GetHeight();
     int rtHeight = renderTarget ? renderTarget->GetHeight() : graphics_->GetHeight();
@@ -199,9 +197,6 @@ void View::Render()
     graphics_->SetTexture(TU_FACESELECT, renderer_->GetFaceSelectCubeMap());
     graphics_->SetTexture(TU_FACESELECT, renderer_->GetFaceSelectCubeMap());
     graphics_->SetTexture(TU_INDIRECTION, renderer_->GetIndirectionCubeMap());
     graphics_->SetTexture(TU_INDIRECTION, renderer_->GetIndirectionCubeMap());
     
     
-    // Calculate view-global shader parameters
-    CalculateShaderParameters();
-    
     // Reset the light optimization stencil reference value
     // Reset the light optimization stencil reference value
     lightStencilValue_ = 1;
     lightStencilValue_ = 1;
     
     
@@ -230,7 +225,7 @@ void View::Render()
     // "Forget" the camera, octree and zone after rendering
     // "Forget" the camera, octree and zone after rendering
     camera_ = 0;
     camera_ = 0;
     octree_ = 0;
     octree_ = 0;
-    zone_ = 0;
+    cameraZone_ = 0;
     frame_.camera_ = 0;
     frame_.camera_ = 0;
 }
 }
 
 
@@ -240,19 +235,33 @@ void View::GetDrawables()
     
     
     Vector3 cameraPos = camera_->GetWorldPosition();
     Vector3 cameraPos = camera_->GetWorldPosition();
     
     
-    // Get zones & find the zone camera is in
-    PointOctreeQuery query(tempDrawables_, cameraPos, DRAWABLE_ZONE, camera_->GetViewMask());
-    octree_->GetDrawables(query);
-    
-    int highestZonePriority = M_MIN_INT;
-    for (unsigned i = 0; i < tempDrawables_.Size(); ++i)
+    // Find the camera & farclip zones
     {
     {
-        Zone* zone = static_cast<Zone*>(tempDrawables_[i]);
-        if (zone->IsInside(cameraPos) && zone->GetPriority() > highestZonePriority)
+        PROFILE(FindCameraZone);
+        Vector3 cameraPos = camera_->GetWorldPosition();
+        Vector3 farClipPos = cameraPos + camera_->GetNode()->GetWorldDirection() * camera_->GetFarClip();
+        // Get default zone in case we do not have anything else
+        Zone* defaultZone = renderer_->GetDefaultZone();
+        cameraZone_ = defaultZone;
+        
+        PointOctreeQuery query(tempZones_, cameraPos, DRAWABLE_ZONE);
+        PODVector<Zone*>& zoneResult = reinterpret_cast<PODVector<Zone*>&>(tempZones_);
+        int bestPriority = M_MIN_INT;
+        Zone* newZone = 0;
+        
+        for (PODVector<Zone*>::Iterator i = zoneResult.Begin(); i != zoneResult.End(); ++i)
         {
         {
-            zone_ = zone;
-            highestZonePriority = zone->GetPriority();
+            Zone* zone = *i;
+            int priority = zone->GetPriority();
+            if (zone->IsInside(cameraPos) && priority > bestPriority)
+            {
+                newZone = zone;
+                bestPriority = priority;
+            }
         }
         }
+        
+        if (newZone)
+            cameraZone_ = newZone;
     }
     }
     
     
     // If occlusion in use, get & render the occluders, then build the depth buffer hierarchy
     // If occlusion in use, get & render the occluders, then build the depth buffer hierarchy
@@ -309,6 +318,10 @@ void View::GetDrawables()
         unsigned flags = drawable->GetDrawableFlags();
         unsigned flags = drawable->GetDrawableFlags();
         if (flags & DRAWABLE_GEOMETRY)
         if (flags & DRAWABLE_GEOMETRY)
         {
         {
+            // Find new zone for the drawable if necessary
+            if (!drawable->GetZone() && !cameraZoneOverride_)
+                drawable->FindZone(tempZones_);
+            
             drawable->ClearLights();
             drawable->ClearLights();
             drawable->MarkInView(frame_);
             drawable->MarkInView(frame_);
             drawable->UpdateGeometry(frame_);
             drawable->UpdateGeometry(frame_);
@@ -334,11 +347,6 @@ void View::GetDrawables()
         else if (flags & DRAWABLE_LIGHT)
         else if (flags & DRAWABLE_LIGHT)
         {
         {
             Light* light = static_cast<Light*>(drawable);
             Light* light = static_cast<Light*>(drawable);
-            
-            // Skip if light is culled by the zone
-            if (!(light->GetViewMask() & zone_->GetViewMask()))
-                continue;
-            
             light->MarkInView(frame_);
             light->MarkInView(frame_);
             lights_.Push(light);
             lights_.Push(light);
         }
         }
@@ -346,11 +354,11 @@ void View::GetDrawables()
     
     
     // Sort the lights to brightest/closest first
     // Sort the lights to brightest/closest first
     for (unsigned i = 0; i < lights_.Size(); ++i)
     for (unsigned i = 0; i < lights_.Size(); ++i)
-	{
-		Light* light = lights_[i];
+    {
+        Light* light = lights_[i];
         light->SetIntensitySortValue(camera_->GetDistance(light->GetWorldPosition()));
         light->SetIntensitySortValue(camera_->GetDistance(light->GetWorldPosition()));
-	}
-
+    }
+    
     Sort(lights_.Begin(), lights_.End(), CompareDrawables);
     Sort(lights_.Begin(), lights_.End(), CompareDrawables);
 }
 }
 
 
@@ -508,6 +516,7 @@ void View::GetBatches()
                 
                 
                 // Fill the rest of the batch
                 // Fill the rest of the batch
                 baseBatch.camera_ = camera_;
                 baseBatch.camera_ = camera_;
+                baseBatch.zone_ = GetZone(drawable);
                 baseBatch.hasPriority_ = true;
                 baseBatch.hasPriority_ = true;
                 
                 
                 Pass* pass = 0;
                 Pass* pass = 0;
@@ -589,6 +598,7 @@ void View::GetLitBatches(Drawable* drawable, LightBatchQueue& lightQueue)
         // Fill the rest of the batch
         // Fill the rest of the batch
         litBatch.camera_ = camera_;
         litBatch.camera_ = camera_;
         litBatch.lightQueue_ = &lightQueue;
         litBatch.lightQueue_ = &lightQueue;
+        litBatch.zone_ = GetZone(drawable);
         
         
         // Check from the ambient pass whether the object is opaque or transparent
         // Check from the ambient pass whether the object is opaque or transparent
         Pass* ambientPass = tech->GetPass(PASS_BASE);
         Pass* ambientPass = tech->GetPass(PASS_BASE);
@@ -627,7 +637,7 @@ void View::RenderBatches()
         graphics_->SetRenderTarget(0, renderTarget_);
         graphics_->SetRenderTarget(0, renderTarget_);
         graphics_->SetDepthStencil(depthStencil_);
         graphics_->SetDepthStencil(depthStencil_);
         graphics_->SetViewport(screenRect_);
         graphics_->SetViewport(screenRect_);
-        graphics_->Clear(CLEAR_COLOR | CLEAR_DEPTH | CLEAR_STENCIL, zone_->GetFogColor());
+        graphics_->Clear(CLEAR_COLOR | CLEAR_DEPTH | CLEAR_STENCIL, cameraZone_->GetFogColor());
         
         
         RenderBatchQueue(baseQueue_);
         RenderBatchQueue(baseQueue_);
     }
     }
@@ -779,7 +789,7 @@ unsigned View::ProcessLight(Light* light)
     case LIGHT_DIRECTIONAL:
     case LIGHT_DIRECTIONAL:
         for (unsigned i = 0; i < geometries_.Size(); ++i)
         for (unsigned i = 0; i < geometries_.Size(); ++i)
         {
         {
-            if (geometries_[i]->GetLightMask() & light->GetLightMask())
+            if (GetLightMask(geometries_[i]) & light->GetLightMask())
                 litGeometries_.Push(geometries_[i]);
                 litGeometries_.Push(geometries_[i]);
         }
         }
         break;
         break;
@@ -790,7 +800,7 @@ unsigned View::ProcessLight(Light* light)
             octree_->GetDrawables(query);
             octree_->GetDrawables(query);
             for (unsigned i = 0; i < tempDrawables_.Size(); ++i)
             for (unsigned i = 0; i < tempDrawables_.Size(); ++i)
             {
             {
-                if (tempDrawables_[i]->IsInView(frame_) && (tempDrawables_[i]->GetLightMask() & light->GetLightMask()))
+                if (tempDrawables_[i]->IsInView(frame_) && (GetLightMask(tempDrawables_[i]) & light->GetLightMask()))
                     litGeometries_.Push(tempDrawables_[i]);
                     litGeometries_.Push(tempDrawables_[i]);
             }
             }
         }
         }
@@ -803,7 +813,7 @@ unsigned View::ProcessLight(Light* light)
             octree_->GetDrawables(query);
             octree_->GetDrawables(query);
             for (unsigned i = 0; i < tempDrawables_.Size(); ++i)
             for (unsigned i = 0; i < tempDrawables_.Size(); ++i)
             {
             {
-                if (tempDrawables_[i]->IsInView(frame_) && (tempDrawables_[i]->GetLightMask() & light->GetLightMask()))
+                if (tempDrawables_[i]->IsInView(frame_) && (GetLightMask(tempDrawables_[i]) & light->GetLightMask()))
                     litGeometries_.Push(tempDrawables_[i]);
                     litGeometries_.Push(tempDrawables_[i]);
             }
             }
         }
         }
@@ -941,7 +951,7 @@ void View::ProcessShadowCasters(Light* light, unsigned splitIndex, const PODVect
             continue;
             continue;
         
         
         // Check light mask
         // Check light mask
-        if (!(drawable->GetLightMask() & light->GetLightMask()))
+        if (!(GetLightMask(drawable) & light->GetLightMask()))
             continue;
             continue;
         
         
         // Project shadow caster bounding box to light view space for visibility check
         // Project shadow caster bounding box to light view space for visibility check
@@ -1251,7 +1261,7 @@ void View::SetupDirLightShadowCamera(Camera* shadowCamera, Light* light, float n
             if (geomBox.Size().LengthFast() < M_LARGE_VALUE)
             if (geomBox.Size().LengthFast() < M_LARGE_VALUE)
             {
             {
                 if (geometryDepthBounds_[i].min_ <= farSplit && geometryDepthBounds_[i].max_ >= nearSplit &&
                 if (geometryDepthBounds_[i].min_ <= farSplit && geometryDepthBounds_[i].max_ >= nearSplit &&
-                    (geometries_[i]->GetLightMask() & light->GetLightMask()))
+                    (GetLightMask(geometries_[i]) & light->GetLightMask()))
                     litGeometriesBox.Merge(geomBox);
                     litGeometriesBox.Merge(geomBox);
             }
             }
         }
         }
@@ -1390,6 +1400,19 @@ void View::QuantizeDirLightShadowCamera(Camera* shadowCamera, Light* light, cons
     }
     }
 }
 }
 
 
+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();
+}
+
 Technique* View::GetTechnique(Drawable* drawable, Material*& material)
 Technique* View::GetTechnique(Drawable* drawable, Material*& material)
 {
 {
     if (!material)
     if (!material)
@@ -1519,40 +1542,6 @@ void View::PrepareInstancingBuffer()
     }
     }
 }
 }
 
 
-void View::CalculateShaderParameters()
-{
-    Time* time = GetSubsystem<Time>();
-    
-    float farClip = camera_->GetFarClip();
-    float nearClip = camera_->GetNearClip();
-    float fogStart = Min(zone_->GetFogStart(), farClip);
-    float fogEnd = Min(zone_->GetFogEnd(), farClip);
-    if (fogStart >= fogEnd * (1.0f - M_LARGE_EPSILON))
-        fogStart = fogEnd * (1.0f - M_LARGE_EPSILON);
-    float fogRange = Max(fogEnd - fogStart, M_EPSILON);
-    Vector4 fogParams(fogStart / farClip, fogEnd / farClip, 1.0f / (fogRange / farClip), 0.0f);
-    
-    Vector4 depthMode = Vector4::ZERO;
-    if (camera_->IsOrthographic())
-    {
-        depthMode.x_ = 1.0f;
-        #ifdef USE_OPENGL
-        depthMode.z_ = 0.5f;
-        depthMode.w_ = 0.5f;
-        #else
-        depthMode.z_ = 1.0f;
-        #endif
-    }
-    else
-        depthMode.w_ = 1.0f / camera_->GetFarClip();
-    
-    shaderParameters_.Clear();
-    shaderParameters_[VSP_DEPTHMODE] = depthMode;
-    shaderParameters_[PSP_AMBIENTCOLOR] = zone_->GetAmbientColor().ToVector4();
-    shaderParameters_[PSP_FOGCOLOR] = zone_->GetFogColor().ToVector4(),
-    shaderParameters_[PSP_FOGPARAMS] = fogParams;
-}
-
 void View::RenderBatchQueue(const BatchQueue& queue, bool useScissor)
 void View::RenderBatchQueue(const BatchQueue& queue, bool useScissor)
 {
 {
     graphics_->SetScissorTest(false);
     graphics_->SetScissorTest(false);
@@ -1563,13 +1552,13 @@ void View::RenderBatchQueue(const BatchQueue& queue, bool useScissor)
         queue.sortedPriorityBatchGroups_.End(); ++i)
         queue.sortedPriorityBatchGroups_.End(); ++i)
     {
     {
         BatchGroup* group = *i;
         BatchGroup* group = *i;
-        group->Draw(graphics_, renderer_, shaderParameters_);
+        group->Draw(graphics_, renderer_);
     }
     }
     // Priority non-instanced
     // Priority non-instanced
     for (PODVector<Batch*>::ConstIterator i = queue.sortedPriorityBatches_.Begin(); i != queue.sortedPriorityBatches_.End(); ++i)
     for (PODVector<Batch*>::ConstIterator i = queue.sortedPriorityBatches_.Begin(); i != queue.sortedPriorityBatches_.End(); ++i)
     {
     {
         Batch* batch = *i;
         Batch* batch = *i;
-        batch->Draw(graphics_, renderer_, shaderParameters_);
+        batch->Draw(graphics_, renderer_);
     }
     }
     
     
     // Non-priority instanced
     // Non-priority instanced
@@ -1578,7 +1567,7 @@ void View::RenderBatchQueue(const BatchQueue& queue, bool useScissor)
         BatchGroup* group = *i;
         BatchGroup* group = *i;
         if (useScissor && group->lightQueue_)
         if (useScissor && group->lightQueue_)
             OptimizeLightByScissor(group->lightQueue_->light_);
             OptimizeLightByScissor(group->lightQueue_->light_);
-        group->Draw(graphics_, renderer_, shaderParameters_);
+        group->Draw(graphics_, renderer_);
     }
     }
     // Non-priority non-instanced
     // Non-priority non-instanced
     for (PODVector<Batch*>::ConstIterator i = queue.sortedBatches_.Begin(); i != queue.sortedBatches_.End(); ++i)
     for (PODVector<Batch*>::ConstIterator i = queue.sortedBatches_.Begin(); i != queue.sortedBatches_.End(); ++i)
@@ -1591,7 +1580,7 @@ void View::RenderBatchQueue(const BatchQueue& queue, bool useScissor)
             else
             else
                 graphics_->SetScissorTest(false);
                 graphics_->SetScissorTest(false);
         }
         }
-        batch->Draw(graphics_, renderer_, shaderParameters_);
+        batch->Draw(graphics_, renderer_);
     }
     }
 }
 }
 
 
@@ -1605,13 +1594,13 @@ void View::RenderLightBatchQueue(const BatchQueue& queue, Light* light)
         queue.sortedPriorityBatchGroups_.End(); ++i)
         queue.sortedPriorityBatchGroups_.End(); ++i)
     {
     {
         BatchGroup* group = *i;
         BatchGroup* group = *i;
-        group->Draw(graphics_, renderer_, shaderParameters_);
+        group->Draw(graphics_, renderer_);
     }
     }
     // Priority non-instanced
     // Priority non-instanced
     for (PODVector<Batch*>::ConstIterator i = queue.sortedPriorityBatches_.Begin(); i != queue.sortedPriorityBatches_.End(); ++i)
     for (PODVector<Batch*>::ConstIterator i = queue.sortedPriorityBatches_.Begin(); i != queue.sortedPriorityBatches_.End(); ++i)
     {
     {
         Batch* batch = *i;
         Batch* batch = *i;
-        batch->Draw(graphics_, renderer_, shaderParameters_);
+        batch->Draw(graphics_, renderer_);
     }
     }
     
     
     // All base passes have been drawn. Optimize at this point by both stencil volume and scissor
     // All base passes have been drawn. Optimize at this point by both stencil volume and scissor
@@ -1622,13 +1611,13 @@ void View::RenderLightBatchQueue(const BatchQueue& queue, Light* light)
     for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedBatchGroups_.Begin(); i != queue.sortedBatchGroups_.End(); ++i)
     for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedBatchGroups_.Begin(); i != queue.sortedBatchGroups_.End(); ++i)
     {
     {
         BatchGroup* group = *i;
         BatchGroup* group = *i;
-        group->Draw(graphics_, renderer_, shaderParameters_);
+        group->Draw(graphics_, renderer_);
     }
     }
     // Non-priority non-instanced
     // Non-priority non-instanced
     for (PODVector<Batch*>::ConstIterator i = queue.sortedBatches_.Begin(); i != queue.sortedBatches_.End(); ++i)
     for (PODVector<Batch*>::ConstIterator i = queue.sortedBatches_.Begin(); i != queue.sortedBatches_.End(); ++i)
     {
     {
         Batch* batch = *i;
         Batch* batch = *i;
-        batch->Draw(graphics_, renderer_, shaderParameters_);
+        batch->Draw(graphics_, renderer_);
     }
     }
 }
 }
 
 

+ 11 - 9
Engine/Graphics/View.h

@@ -71,8 +71,6 @@ public:
     Octree* GetOctree() const { return octree_; }
     Octree* GetOctree() const { return octree_; }
     /// Return camera.
     /// Return camera.
     Camera* GetCamera() const { return camera_; }
     Camera* GetCamera() const { return camera_; }
-    /// Return zone.
-    Zone* GetZone() const { return zone_; }
     /// Return the render target. 0 if using the backbuffer.
     /// Return the render target. 0 if using the backbuffer.
     RenderSurface* GetRenderTarget() const { return renderTarget_; }
     RenderSurface* GetRenderTarget() const { return renderTarget_; }
     /// Return the depth stencil. 0 if using the backbuffer's depth stencil.
     /// Return the depth stencil. 0 if using the backbuffer's depth stencil.
@@ -125,6 +123,10 @@ private:
     const Rect& GetLightScissor(Light* light);
     const Rect& GetLightScissor(Light* light);
     /// Split directional or point light for shadow rendering.
     /// Split directional or point light for shadow rendering.
     unsigned SplitLight(Light* light);
     unsigned SplitLight(Light* light);
+    /// Return the drawable's zone, or camera/default zone if not set.
+    Zone* GetZone(Drawable* drawable);
+    /// Return the drawable's light mask, considering also its zone.
+    unsigned GetLightMask(Drawable* drawable);
     /// Return material technique, considering the drawable's LOD distance.
     /// Return material technique, considering the drawable's LOD distance.
     Technique* GetTechnique(Drawable* drawable, Material*& material);
     Technique* GetTechnique(Drawable* drawable, Material*& material);
     /// Check if material should render an auxiliary view (if it has a camera attached.)
     /// Check if material should render an auxiliary view (if it has a camera attached.)
@@ -133,8 +135,6 @@ private:
     void SortBatches();
     void SortBatches();
     /// Prepare instancing buffer by filling it with all instance transforms.
     /// Prepare instancing buffer by filling it with all instance transforms.
     void PrepareInstancingBuffer();
     void PrepareInstancingBuffer();
-    /// Calculate view-global shader parameters.
-    void CalculateShaderParameters();
     /// Render everything in a batch queue, priority batches first.
     /// Render everything in a batch queue, priority batches first.
     void RenderBatchQueue(const BatchQueue& queue, bool useScissor = false);
     void RenderBatchQueue(const BatchQueue& queue, bool useScissor = false);
     /// Render batches lit by a specific light.
     /// Render batches lit by a specific light.
@@ -150,8 +150,8 @@ private:
     Octree* octree_;
     Octree* octree_;
     /// Camera to use.
     /// Camera to use.
     Camera* camera_;
     Camera* camera_;
-    /// Zone to get global rendering settings from.
-    Zone* zone_;
+    /// Zone the camera is inside, or default zone if not assigned.
+    Zone* cameraZone_;
     /// Color buffer to use.
     /// Color buffer to use.
     RenderSurface* renderTarget_;
     RenderSurface* renderTarget_;
     /// Depth buffer to use.
     /// Depth buffer to use.
@@ -194,6 +194,8 @@ private:
     PODVector<Drawable*> litGeometries_;
     PODVector<Drawable*> litGeometries_;
     /// Temporary drawable query result.
     /// Temporary drawable query result.
     PODVector<Drawable*> tempDrawables_;
     PODVector<Drawable*> tempDrawables_;
+    /// Temporary zone query result.
+    PODVector<Drawable*> tempZones_;
     /// Geometry objects.
     /// Geometry objects.
     PODVector<Drawable*> geometries_;
     PODVector<Drawable*> geometries_;
     /// Occluder objects.
     /// Occluder objects.
@@ -208,8 +210,6 @@ private:
     HashSet<Drawable*> maxLightsDrawables_;
     HashSet<Drawable*> maxLightsDrawables_;
     /// Light queue indices of processed lights.
     /// Light queue indices of processed lights.
     Map<Light*, unsigned> lightQueueIndex_;
     Map<Light*, unsigned> lightQueueIndex_;
-    /// View-global shader parameters.
-    HashMap<StringHash, Vector4> shaderParameters_;
     /// Cache for light scissor queries.
     /// Cache for light scissor queries.
     HashMap<Light*, Rect> lightScissorCache_;
     HashMap<Light*, Rect> lightScissorCache_;
     /// Base pass batches.
     /// Base pass batches.
@@ -222,6 +222,8 @@ private:
     BatchQueue postAlphaQueue_;
     BatchQueue postAlphaQueue_;
     /// Light queues.
     /// Light queues.
     Vector<LightBatchQueue> lightQueues_;
     Vector<LightBatchQueue> lightQueues_;
-    /// Current stencil value for light optimization;
+    /// Current stencil value for light optimization.
     unsigned char lightStencilValue_;
     unsigned char lightStencilValue_;
+    /// Camera zone's override flag.
+    bool cameraZoneOverride_;
 };
 };

+ 3 - 1
Engine/Graphics/Zone.cpp

@@ -39,7 +39,8 @@ Zone::Zone(Context* context) :
     fogColor_(DEFAULT_FOG_COLOR),
     fogColor_(DEFAULT_FOG_COLOR),
     fogStart_(DEFAULT_FOGSTART),
     fogStart_(DEFAULT_FOGSTART),
     fogEnd_(DEFAULT_FOGEND),
     fogEnd_(DEFAULT_FOGEND),
-    priority_(0)
+    priority_(0),
+    override_(false)
 {
 {
     drawableFlags_ =  DRAWABLE_ZONE;
     drawableFlags_ =  DRAWABLE_ZONE;
 }
 }
@@ -59,6 +60,7 @@ void Zone::RegisterObject(Context* context)
     ATTRIBUTE(Zone, VAR_FLOAT, "Fog Start", fogStart_, DEFAULT_FOGSTART, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_FLOAT, "Fog Start", fogStart_, DEFAULT_FOGSTART, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_FLOAT, "Fog End", fogEnd_, DEFAULT_FOGEND, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_FLOAT, "Fog End", fogEnd_, DEFAULT_FOGEND, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_BOOL, "Is Visible", visible_, true, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_BOOL, "Is Visible", visible_, true, AM_DEFAULT);
+    ATTRIBUTE(Zone, VAR_BOOL, "Override Mode", override_, 0, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "Priority", priority_, 0, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "Priority", priority_, 0, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "View Mask", viewMask_, DEFAULT_VIEWMASK, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "View Mask", viewMask_, DEFAULT_VIEWMASK, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "Light Mask", lightMask_, DEFAULT_LIGHTMASK, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "Light Mask", lightMask_, DEFAULT_LIGHTMASK, AM_DEFAULT);

+ 6 - 0
Engine/Graphics/Zone.h

@@ -54,6 +54,8 @@ public:
     void SetFogEnd(float end);
     void SetFogEnd(float end);
     /// %Set zone priority. If camera is inside several zones, the one with highest priority is used.
     /// %Set zone priority. If camera is inside several zones, the one with highest priority is used.
     void SetPriority(int priority);
     void SetPriority(int priority);
+    /// %Set override mode. If camera is inside an override zone, it will also be used for all drawables.
+    void SetOverride(bool enable);
     
     
     /// Return bounding box.
     /// Return bounding box.
     const BoundingBox& GetBoundingBox() const { return boundingBox_; }
     const BoundingBox& GetBoundingBox() const { return boundingBox_; }
@@ -67,6 +69,8 @@ public:
     float GetFogEnd() const { return fogEnd_; }
     float GetFogEnd() const { return fogEnd_; }
     /// Return zone priority.
     /// Return zone priority.
     int GetPriority() const { return priority_; }
     int GetPriority() const { return priority_; }
+    /// Return override mode.
+    bool GetOverride() const { return override_; }
     
     
     /// Check whether a point is inside.
     /// Check whether a point is inside.
     virtual bool IsInside(const Vector3& point);
     virtual bool IsInside(const Vector3& point);
@@ -87,4 +91,6 @@ protected:
     float fogEnd_;
     float fogEnd_;
     /// Zone priority.
     /// Zone priority.
     int priority_;
     int priority_;
+    /// Override mode.
+    bool override_;
 };
 };