トップ 一覧 検索 ヘルプ RSS ログイン

unity_script_openglの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!!!OpenGL描画
スクリーン上で独自のOpenGL描画を行うことができます。

!!スクリーンに2D描画
ここではメインカメラにスクリプトを割り当て、そこで記述します。
MonoBehaviour派生クラスの「OnPostRender」関数を使用することで、カメラに対するOpenGL描画が行われます。
 private Material m_material;
 
 void Start () {
   // マテリアルの生成.
   m_material = new Material(
     "Shader \"myShader\" {" +
     "  SubShader {" +
     "    Pass {" +
     "       ZWrite Off" +
     "       Cull Off" + 
     "       BindChannels {" +
     "         Bind \"vertex\", vertex Bind \"color\", color" +
     "       }" +
     "    }" +
     "  }" +
     "}"
   );
   m_material.hideFlags = HideFlags.HideAndDontSave;
   m_material.shader.hideFlags = HideFlags.HideAndDontSave;
 }
 
 void OnPostRender() {
   if (m_material != null) {
       m_material.SetPass(0);  // マテリアルのパス0を割り当て.
   
       GL.PushMatrix();
       GL.LoadOrtho();   // 2D描画として処理.
       GL.Begin(GL.TRIANGLES);
 
         GL.Color(Color.red);
         GL.Vertex3( 0.0f, 0.0f, 0.0f );
 
         GL.Color(Color.green);
         GL.Vertex3(0.0f, 1.0f, 0.0f );
 
         GL.Color(Color.blue);
         GL.Vertex3(0.5f, 0.5f, 0.0f );
 
       GL.End();
       GL.PopMatrix();
   }
 }
これを実行すると以下のように描画されます。
{{ref_image unity_opengl_001.png}}
スクリーンの左下を(0, 0)、右上を(1, 1)として、三角形を描画しています。
この際に「GL.Color」で指定した色が頂点カラーとして使用されてグラデーションします。
三角形は「時計回りが表」となる点に注意してください。逆向きだと隠れて見えなくなります。

!マテリアルの生成
 m_material = new Material("xxxx");
のところは、[[シェーダーのソース|unity_shader_basic]]を記載しています。
シェーダーとしては、以下のものをテキストで格納しています。
 Shader "myShader" {
   SubShader {
     Pass {
       ZWrite Off
       Cull Off
       BindChannels {
         Bind "vertex", vertex Bind "color", color
       }
     }
   }
 }
「ZWrite Off」でZバッファへの書き込みは無効化、「Cull Off」で裏面は非表示。
「BindChannels」内の記述により、GL.Colorで指定する色を頂点カラーとして指定します。

!GL描画
 m_material.SetPass(0);
で描画で使用するマテリアルの指定。

「GL.PushMatrix();」〜「GL.PopMatrix();」で囲むことにより、変換行列を使用後に復帰できるようにします。

「GL.LoadOrtho()」でスクリーンにあわせた2D描画を行います。スクリーンの左下が(0, 0)、右上が(1, 1)になります。

「GL.Begin(GL.TRIANGLES);」〜「GL.End();」内で三角形の頂点の色と頂点座標を指定します。
「GL.Color」の指定は、GL.Begin 〜 GL.Endの中で指定しないと反映されません。

!!スクリーンに2D描画 +テクスチャ指定
 private Texture2D m_texture;
 private Material m_material;
 
 void Start () {
    // テクスチャの作成.
    m_texture = new Texture2D(32, 32, TextureFormat.ARGB32, false);
    for (int y = 0; y < m_texture.height; y++) {
        for (int x = 0; x < m_texture.width; x++) {
            if ((x & 1) != 0 && (y & 1) == 0) m_texture.SetPixel(x, y, Color.red);
            else m_texture.SetPixel(x, y, Color.white);
        }
    }
    m_texture.Apply();
    
    // マテリアルの作成.
    m_material = new Material(
         "Shader \"myShader\" {" +
         "  Properties {" +
         "    _MainTex (\"Base (RGB)\", 2D) = \"white\" {}" +
         "  }" +
         "  SubShader {" +
         "    Pass {" +
         "       ZWrite Off" +
         "       Cull Off" +            
         "       BindChannels {" +
         "         Bind \"vertex\", vertex Bind \"color\", color" +
         "       }" +
         "       SetTexture [_MainTex] {" +
         "         constantColor (1.0, 1.0, 1.0, 1.0)" +
         "         Combine texture * primary DOUBLE, texture * constant" +
         "       }" +           
         "    }" +
         "  }" +
         "}"
    );
    m_material.hideFlags = HideFlags.HideAndDontSave;
    m_material.shader.hideFlags = HideFlags.HideAndDontSave;
    m_material.mainTexture = m_texture;
    m_material.color = Color.white;
 }
 
 void OnPostRender() {
    if (m_material != null) {
        m_material.SetPass(0);
        GL.PushMatrix();
        GL.LoadOrtho();
        GL.Begin(GL.TRIANGLES);
            GL.Color(Color.white);
 
            GL.TexCoord2(0.5f, 1.0f);
            GL.Vertex3( 0.0f, 0.0f, 0.0f );
 
            GL.TexCoord2(0.0f, 0.0f);
            GL.Vertex3(0.0f, 1.0f, 0.0f );
 
            GL.TexCoord2(1.0f, 0.0f);
            GL.Vertex3(0.5f, 0.5f, 0.0f );
 
        GL.End();
        GL.PopMatrix();
    }
 }
テクスチャ(Texture2D)の作成は「[[テクスチャの作成|unity_script_create_texture2d]]」を参照。
マテリアル作成時のシェーダーのテキストで
         "  Properties {" +
         "    _MainTex (\"Base (RGB)\", 2D) = \"white\" {}" +
         "  }"
の指定でメインテクスチャをパラメータとして指定できるようにします。
         "       SetTexture [_MainTex] {" +
         "         constantColor (1.0, 1.0, 1.0, 1.0)" +
         "         Combine texture * primary DOUBLE, texture * constant" +
         "       }" +           
の箇所でテクスチャ色を取得します。

「m_material.mainTexture = m_texture;」で、生成したm_texture(Texture2D)を割り当てます。

OnPostRender関数内のOpenGL描画部では「GL.TexCoord2」でUV値を指定することで、テクスチャが反映されます。
{{ref_image unity_opengl_002.png}}

!!ラインを描画
ここでは、emptyのGameObjectをシーンに配置し、新しいC#スクリプトを生成してGameObjectに割り当てておきます。
以下、3次元として配置する例です。
 private Material m_lineMaterial;
 
 void Start () {
   // ライン描画用のマテリアルを生成.
   m_lineMaterial = new Material(
     "Shader \"myShader\" {" +
     "  SubShader {" +
     "    Pass {" +
     "       ZWrite Off" +
     "       Cull Off" + 
     "       BindChannels {" +
     "         Bind \"vertex\", vertex Bind \"color\", color" +
     "       }" +
     "    }" +
     "  }" +
     "}"            
   );
   m_lineMaterial.hideFlags = HideFlags.HideAndDontSave;
   m_lineMaterial.shader.hideFlags = HideFlags.HideAndDontSave;
 }
 
 void OnRenderObject() {
    if (m_lineMaterial != null) {
        m_lineMaterial.SetPass(0);
        
        GL.PushMatrix();
        GL.Begin(GL.LINES);
            GL.Color (Color.red);
            GL.Vertex3(0.0f, 0.0f, 0.0f);
            GL.Vertex3(0.0f, 2.0f, 0.0f);
                
            GL.Vertex3(0.0f, 2.0f, 0.0f);
            GL.Vertex3(0.0f, 2.0f, 2.0f);
    
            GL.Vertex3(0.0f, 2.0f, 2.0f);
            GL.Vertex3(0.0f, 0.0f, 2.0f);
            
            GL.Color (Color.green);
            GL.Vertex3(0.0f, 0.0f, 0.0f);
            GL.Vertex3(0.0f, 2.0f, 2.0f);
 
        GL.End();
        GL.PopMatrix();
    }
 }
シェーダーの作成に関しては、面を描画する場合と同じです。
色情報を取得し、それをそのままライン描画の色として反映します。

「OnRenderObject」関数で、「GL.Begin(GL.LINES);」〜「GL.End();」の間にラインの座標指定を行います。
{{ref_image unity_opengl_draw_line.png}}
のように4本のラインが描画されます。中央より少し左に寄っている小さな球が原点位置です。

!!太さのあるラインを描画
UnityのGLでは、太さのあるラインの描画はできないため「GL.Begin (GL.QUADS)」を使って1ラインごとに四角形を描画していきます。
 // 太さのある線を描画.
 void DrawLine2D(Vector3 v0, Vector3 v1, float lineWidth) {
   Vector3 n = ((new Vector3(v1.y, v0.x, 0.0f)) - (new Vector3(v0.y, v1.x, 0.0f))).normalized * lineWidth;
   GL.Vertex3(v0.x - n.x, v0.y - n.y, 0.0f);
   GL.Vertex3(v0.x + n.x, v0.y + n.y, 0.0f);
   GL.Vertex3(v1.x + n.x, v1.y + n.y, 0.0f);
   GL.Vertex3(v1.x - n.x, v1.y - n.y, 0.0f);
 }
 
 void OnRenderObject() {
   if (m_lineMaterial != null) {
     m_lineMaterial.SetPass(0);
    
     float lineWidth = 2.0f;        // ラインの太さ.
            
     // スクリーン上のラインの太さに変換.
     float thisWidth = 1.0f / Screen.width * lineWidth * 0.5f;
            
     GL.PushMatrix();
     GL.LoadOrtho();
     GL.Begin (GL.QUADS);
       GL.Color (Color.red);
       DrawLine2D(new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.8f, 0.0f), thisWidth);
       DrawLine2D(new Vector3(0.0f, 0.8f, 0.0f), new Vector3(0.5f, 0.5f, 0.0f), thisWidth);
       DrawLine2D(new Vector3(0.5f, 0.5f, 0.0f), new Vector3(0.0f, 0.0f, 0.0f), thisWidth);
     GL.End();
     GL.PopMatrix();
   }
 }
{{ref_image unity_opengl_draw_line_with_width.png}}

!!ビューポートの指定
デフォルトでは、スクリーンの左下が(0, 0)、右上が(1, 1)ですが、
Viewportの指定で変更することができます。
 GL.PushMatrix();
 GL.LoadPixelMatrix();
 GL.Viewport(new Rect(0, 0, Screen.width, Screen.height));
 
 ... 何か描画処理.
 
 GL.PopMatrix();
とLoadPixelMatrixとViewportの指定を行うと、スクリーンの左下が(0, 0)、右上が(Screen.width, Screen.height)となります。

!!2D描画を拡張する

GLの描画は太さ1.0のラインを引くかポリゴンを描く、のコマンドしかないです。
これをラップして、

*太さのある線を描画
*破線を描画
*四角形の描画
*円の描画
*ポリゴンの描画

を行うクラスを作成。