!!!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)となります。