2
0
Эх сурвалжийг харах

Allow configuring the minimum instances per batch group to actually render as instanced.

Lasse Öörni 12 жил өмнө
parent
commit
4c2842967e

+ 2 - 0
Docs/ScriptAPI.dox

@@ -2418,6 +2418,7 @@ AnimationState
 Methods:<br>
 - void AddWeight(float)
 - void AddTime(float)
+- void Apply()
 
 Properties:<br>
 - int refs (readonly)
@@ -3033,6 +3034,7 @@ Properties:<br>
 - int maxShadowMaps
 - bool reuseShadowMaps
 - bool dynamicInstancing
+- int minInstances
 - int maxInstanceTriangles
 - int maxSortedInstances
 - int maxOccluderTriangles

+ 2 - 0
Engine/Engine/GraphicsAPI.cpp

@@ -1091,6 +1091,8 @@ static void RegisterRenderer(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Renderer", "bool get_reuseShadowMaps() const", asMETHOD(Renderer, GetReuseShadowMaps), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_dynamicInstancing(bool)", asMETHOD(Renderer, SetDynamicInstancing), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "bool get_dynamicInstancing() const", asMETHOD(Renderer, GetDynamicInstancing), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Renderer", "void set_minInstances(int)", asMETHOD(Renderer, SetMinInstances), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Renderer", "int get_minInstances() const", asMETHOD(Renderer, GetMinInstances), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_maxInstanceTriangles(int)", asMETHOD(Renderer, SetMaxInstanceTriangles), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "int get_maxInstanceTriangles() const", asMETHOD(Renderer, GetMaxInstanceTriangles), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_maxSortedInstances(int)", asMETHOD(Renderer, SetMaxSortedInstances), asCALL_THISCALL);

+ 6 - 0
Engine/Graphics/Renderer.cpp

@@ -267,6 +267,7 @@ Renderer::Renderer(Context* context) :
     shadowQuality_(SHADOWQUALITY_HIGH_16BIT),
     maxShadowMaps_(1),
     maxShadowCascades_(MAX_CASCADE_SPLITS),
+    minInstances_(2),
     maxInstanceTriangles_(500),
     maxSortedInstances_(1000),
     maxOccluderTriangles_(5000),
@@ -441,6 +442,11 @@ void Renderer::SetDynamicInstancing(bool enable)
     dynamicInstancing_ = enable;
 }
 
+void Renderer::SetMinInstances(int instances)
+{
+    minInstances_ = Max(instances, 2);
+}
+
 void Renderer::SetMaxInstanceTriangles(int triangles)
 {
     maxInstanceTriangles_ = Max(triangles, 0);

+ 6 - 0
Engine/Graphics/Renderer.h

@@ -195,6 +195,8 @@ public:
     void SetMaxShadowCascades(int cascades);
     /// Set dynamic instancing on/off.
     void SetDynamicInstancing(bool enable);
+    /// Set minimum number of instances required in a batch group to render as instanced.
+    void SetMinInstances(int instances);
     /// Set maximum number of triangles per object for instancing.
     void SetMaxInstanceTriangles(int triangles);
     /// Set maximum number of sorted instances per batch group. If exceeded, instances are rendered unsorted.
@@ -238,6 +240,8 @@ public:
     int GetMaxShadowCascades() const { return maxShadowCascades_; }
     /// Return whether dynamic instancing is in use.
     bool GetDynamicInstancing() const { return dynamicInstancing_; }
+    /// Return minimum number of instances required in a batch group to render as instanced.
+    int GetMinInstances() const { return minInstances_; }
     /// Return maximum number of triangles per object for instancing.
     int GetMaxInstanceTriangles() const { return maxInstanceTriangles_; }
     /// Return maximum number of sorted instances per batch group.
@@ -455,6 +459,8 @@ private:
     int maxShadowMaps_;
     /// Maximum number of directional light shadow cascades.
     int maxShadowCascades_;
+    /// Minimum number of instances required in a batch group to render as instanced.
+    int minInstances_;
     /// Maximum triangles per object for instancing.
     int maxInstanceTriangles_;
     /// Maximum sorted instances per batch group.

+ 4 - 3
Engine/Graphics/View.cpp

@@ -405,6 +405,7 @@ bool View::Define(RenderSurface* renderTarget, Viewport* viewport)
     drawShadows_ = renderer_->GetDrawShadows();
     materialQuality_ = renderer_->GetMaterialQuality();
     maxOccluderTriangles_ = renderer_->GetMaxOccluderTriangles();
+    minInstances_ = renderer_->GetMinInstances();
     
     // Set possible quality overrides from the camera
     unsigned viewOverrideFlags = camera_->GetViewOverrideFlags();
@@ -2379,7 +2380,7 @@ void View::AddBatchToQueue(BatchQueue& batchQueue, Batch& batch, Technique* tech
         if (i == groups->End())
         {
             // Create a new group based on the batch
-            // In case the group remains as one batch only, do not enable instancing shaders yet
+            // In case the group remains below the instancing limit, do not enable instancing shaders yet
             BatchGroup newGroup(batch);
             newGroup.geometryType_ = GEOM_STATIC;
             renderer_->SetBatchShaders(newGroup, tech, allowShadows);
@@ -2391,8 +2392,8 @@ void View::AddBatchToQueue(BatchQueue& batchQueue, Batch& batch, Technique* tech
         {
             i->second_.instances_.Push(InstanceData(batch.worldTransform_, batch.distance_));
             
-            // Convert to instancing shaders when second batch is added
-            if (i->second_.instances_.Size() == 2)
+            // 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);

+ 2 - 0
Engine/Graphics/View.h

@@ -244,6 +244,8 @@ private:
     int materialQuality_;
     /// Maximum number of occluder triangles.
     int maxOccluderTriangles_;
+    /// Minimum number of instances required in a batch group to render as instanced.
+    int minInstances_;
     /// Highest zone priority currently visible.
     int highestZonePriority_;
     /// Camera zone's override flag.

+ 1 - 1
Engine/Math/AreaAllocator.cpp

@@ -109,7 +109,7 @@ bool AreaAllocator::Allocate(int width, int height, int& x, int& y)
     x = best->left_;
     y = best->top_;
     
-    // Reserved the area by spliting up the remaining free area
+    // Reserve the area by splitting up the remaining free area
     best->left_ = reserved.right_;
     if (best->Height() > 2 * height)
     {

+ 2 - 2
Engine/Math/AreaAllocator.h

@@ -40,9 +40,9 @@ public:
     void Reset(int width, int height);
     /// Try to allocate an area. Return true if successful, with x & y coordinates filled.
     bool Allocate(int width, int height, int& x, int& y);
-    /// Return the final width (if it is allowed to grow).
+    /// Return the current width.
     int GetWidth() const { return size_.x_; }
-    /// Return the final height (if it is allowed to grow).
+    /// Return the current height.
     int GetHeight() const { return size_.y_; }
 
 private: