Unity - 使用低階圖形指令GL(Low-level graphics library)在畫面上繪製圖像時遇到的狀況

  一、GL的執行順序是立即執行,所以如果在Update裡面呼叫的話,他會在Camera Render之前執行,而接著Camera的更新會讓你的GL繪圖被蓋掉,所以最好在OnPostRender()裡面呼叫GL指令。




借用官網範例改C#:
static Material lineMaterial;

static void CreateLineMaterial() {
 if( !lineMaterial ) {
  lineMaterial = new Material( "Shader \"Lines/Colored Blended\" {" +
   "SubShader { Pass { " +
   "    Blend SrcAlpha OneMinusSrcAlpha " +
   "    ZWrite Off Cull Off Fog { Mode Off } " +
   "    BindChannels {" +
   "      Bind \"vertex\", vertex Bind \"color\", color }" +
   "} } }" );
  lineMaterial.hideFlags = HideFlags.HideAndDontSave;
  lineMaterial.shader.hideFlags = HideFlags.HideAndDontSave;
 }
}

//在PostRender裡面呼叫GL才可以避免Render順序的問題
void OnPostRender() {
 CreateLineMaterial();
 // set the current material
 lineMaterial.SetPass( 0 );

 //繪製線條,每兩個點一線,請給雙數點
 GL.Begin( GL.LINES );
 GL.Color( new Color(1.0f,1.0f,1.0f,0.5f) );
 GL.Vertex3( 0, 0, 0 );
 GL.Vertex3( 1, 0, 0 );
 GL.End();
}


  二、OnPostRender方法沒有呼叫的狀況,因這個方法只有在這個Script掛載在Camera下面才會呼叫,所以請先檢查有這個方法的Component是否在Camera下。


  三、當有兩個以上的Camera的時候,在ClearFlags都是Skybox的狀況下,只會畫出其中一個Camera的線條(使用上面範例,兩個Camera繪製不同座標線條),另外一個Camera的畫不出來。
  同樣是執行順序的問題,在單一Camera下只要在OnPostRender裡呼叫GL,就可以確保GL是在Camera render後才執行。但是兩個以上的Camera狀況下,兩個Camera的Render順序不同,OnPostRender只能在該掛載的Camera render過後執行,接著第二個Camera開始更新,就會覆蓋掉第一個Camera的資料(ClearFlag:Skybox)
  解決辦法就是讓OnPostRender裡面的GL等到該frame的尾端執行,確保所有的Camera都已經Render完畢,所以直接在OnPostRender()開頭加上WaitForEndOfFrame()就可以了。

C#版本,其餘部分跟第一個範例相同
//在PostRender開頭呼叫WaitForEndOfFrame調整順序的問題
IEnumerator OnPostRender() {
 yield return new WaitForEndOfFrame();

 CreateLineMaterial();
 // set the current material
 lineMaterial.SetPass( 0 );

 //繪製線條,每兩個點一線,請給雙數點
 GL.Begin( GL.LINES );
 GL.Color( new Color(1.0f,1.0f,1.0f,0.5f) );
 GL.Vertex3( 0, 0, 0 );
 GL.Vertex3( 1, 0, 0 );
 GL.End();
}


No comments:

Post a Comment