NGUI中UIPanel和DrawCall的性能问题

NGUI将使用相同atlas的组件,归类到一个drawcall中,也就是这些组件的绘制,只消耗一次gl调用。这样来提高gup的绘制效率。

其原理如下:

     UPPanel作为drawcall的组织归类结构,以下UIPanel简称panel。panel会根据自己child的层次,将不同的UIWidget归结到不同的drawcall中。

理论归结过程如下:

     将所有的panel的child按照deep排序,如果deep相同,则按照metrial,否则按照metrial的instanceid。

               [System.Diagnostics.DebuggerHidden]

     [System.Diagnostics.DebuggerStepThrough]
     static public int PanelCompareFunc (UIWidget left, UIWidget right)
     {
          if (left.mDepth < right.mDepth) return -1;
          if (left.mDepth > right.mDepth) return 1;
          Material leftMat = left.material;
          Material rightMat = right.material;
          if (leftMat == rightMat) return 0;
          if (leftMat != null) return -1;
          if (rightMat != null) return 1;
          return (leftMat.GetInstanceID() < rightMat.GetInstanceID()) ? -1 : 1;
     }
从最小的开始查起,标记最小的使用的atlas。进入下一个,如果和上一个使用同一个atlas,则将这两个uiwidget归纳在同一个drawcall里。如果是不同的atlas,则创建不同的drawcall。

注意:

     1、即使使用同一个atals,如果deep不同,并且位于deep1和deep2之间有使用其他atals的widget,则也会产生两个drawcall。

     (原因:不同的深度间,不可能同一个drawcall绘制,会出现遮挡倒序的问题。

          注意事项:如果两个widget使用同一个atlas,则尽量将其deep设置的相同或者相邻,最好是在设计之初,就给不同的atlas设计好其所应该属于的deep。)

     2、尽量将ui上的元素归结到atlas中,这样能增加绘制效率。如果不需要特别为其制定shader的话,尽量用sprite替代texture2d(因为texture2d需要单独一个drawcall)。

相关代码:

     /// <summary>
     /// Fill the geometry fully, processing all widgets and re-creating all draw calls.
     /// </summary>

     void FillAllDrawCalls ()
     {
          for (int i = 0; i < drawCalls.size; ++i)
               UIDrawCall.Destroy(drawCalls.buffer[i]);
          drawCalls.Clear();

          Material mat = null;
          Texture tex = null;
          Shader sdr = null;
          UIDrawCall dc = null;

          if (mSortWidgets) SortWidgets();

          for (int i = 0; i < widgets.size; ++i)
          {
               UIWidget w = widgets.buffer[i];

               if (w.isVisible && w.hasVertices)
               {
                    Material mt = w.material;
                    Texture tx = w.mainTexture;
                    Shader sd = w.shader;

                    if (mat != mt || tex != tx || sdr != sd)
                    {
                         if (mVerts.size != 0)
                         {
                              SubmitDrawCall(dc);
                              dc = null;
                         }

                         mat = mt;
                         tex = tx;
                         sdr = sd;
                    }

                    if (mat != null || sdr != null || tex != null)
                    {
                         if (dc == null)
                         {
                              dc = UIDrawCall.Create(this, mat, tex, sdr);
                              dc.depthStart = w.depth;
                              dc.depthEnd = dc.depthStart;
                              dc.panel = this;
                         }
                         else
                         {
                              int rd = w.depth;
                              if (rd < dc.depthStart) dc.depthStart = rd;
                              if (rd > dc.depthEnd) dc.depthEnd = rd;
                         }

                         w.drawCall = dc;

                         if (generateNormals) w.WriteToBuffers(mVerts, mUvs, mCols, mNorms, mTans);
                         else w.WriteToBuffers(mVerts, mUvs, mCols, null, null);
                    }
               }
               else w.drawCall = null;
          }
          if (mVerts.size != 0) SubmitDrawCall(dc);
     }

猜你喜欢

转载自blog.csdn.net/zhjzhjxzhl/article/details/79743206