質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

OpenGL ES

携帯電話のような組込み機器のためにデザインされたOpenGLのサブセットです。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xamarin

Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

解決済

iOSでのポリゴン、並びにテクスチャの描画についての質問です

JpTomari
JpTomari

総合スコア4

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

OpenGL ES

携帯電話のような組込み機器のためにデザインされたOpenGLのサブセットです。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xamarin

Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

3回答

0評価

0クリップ

411閲覧

投稿2020/10/28 07:51

編集2020/10/29 04:44

概要

XamarinでiOS用のOpenGL描画システムを構築中です。
ポリゴン並びにテクスチャの描画で、作業が詰まってしまいました。

以下にプログラムソースの抜粋を記します。

変数定義

C#

private EAGLContext mContext = null; private uint mFrameBuffer; private uint mRenderBuffer; private int mWidth = -1; private int mHeight = -1; private float mScreenScale = 1.0f; private int[] mTextureID; private NSData[] mTextureBitmap; private int[,] mTextureSize;

描画処理本体

C#

public override void LayoutSubviews() { try { // 画面サイズの取得 CGRect size = UIScreen.MainScreen.Bounds; mWidth = (int)size.Width; mHeight = (int)size.Height; // カレントコンテキストの設定 EAGLContext.SetCurrentContext(mContext); GL.Oes.BindFramebuffer(All.FramebufferOes, mFrameBuffer); // 描画の初期化 GL.Enable((All)EnableCap.Texture2D); GL.Enable((All)EnableCap.AlphaTest); GL.Enable((All)EnableCap.Blend); GL.BlendFunc((All)BlendingFactorSrc.SrcAlphaSaturate, (All)BlendingFactorDest.OneMinusSrcAlpha); // 黄色でクリア GL.ClearColor(1.0f, 1.0f, 0.0f, 1.0f); // バッファクリア GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // テクスチャをアクティブ GL.ActiveTexture(All.Texture0); // ポリゴンの描画 DrawPolygon(0, 0, 100, 100, 1.0f, 0.0f, 0.0f, 1.0f); // テクスチャの描画 BindTexture(0); DrawTexture(0, 0, 0, mTextureSize[0, _X], mTextureSize[0, _Y], false); GL.Oes.BindRenderbuffer(All.RenderbufferOes, mRenderBuffer); mContext.PresentRenderBuffer((uint)All.RenderbufferOes); } catch (Exception e) { } }

テクスチャ読み込み

C#

public void InitTexture(UIImage[] image, int start, int end) { int i; int len = image.Length; // 配列の初期化 mTextureID = new int[len]; mTextureSize = new int[len, _XYWH]; // テクスチャのワークを生成 GL.GenTextures(len, mTextureID); // ゲーム用テクスチャイメージを取得 for (i = start; i < end; i++) { if (i >= len) continue; CGDataProvider dp = image[i].CGImage.DataProvider; NSData data = dp.CopyData(); mTextureBitmap[i] = data; mTextureSize[i, _X] = 0; mTextureSize[i, _Y] = (int)image[i].CGImage.Height; mTextureSize[i, _W] = (int)image[i].CGImage.Width; mTextureSize[i, _H] = (int)-image[i].CGImage.Height; GL.BindTexture(All.Texture2D, mTextureID[i]); GL.TexParameter(All.Texture2D, All.TextureMinFilter, (int)All.Nearest); GL.TexParameter(All.Texture2D, All.TextureMagFilter, (int)All.Nearest); GL.TexImage2D(All.Texture2D, 0, (int)PixelInternalFormat.Palette8Rgba8Oes, mTextureSize[i, _X], mTextureSize[i, _Y], 0, (All)OpenTK.Graphics.ES11.PixelFormat.Rgba, (All)PixelType.UnsignedShort4444, data.Bytes); } }

ポリゴン描画

C#

public void DrawPolygon(int _x, int _y, int _w, int _h, float rr, float gg, float bb, float aa) { int rx = (int)(((float)(_x - (mWidth / 2)) * mScreenScale) + (mWidth / 2)); int ry = (int)(((float)(_y - (mHeight / 2)) * mScreenScale) + (mHeight / 2)); int rw = (int)((float)_w * mScreenScale); int rh = (int)((float)_h * mScreenScale); GL.Disable((All)EnableCap.Texture2D); GL.BindTexture(All.Texture2D, 0); // ポリゴン描画 GL.Color4(rr, gg, bb, aa); GL.VertexPointer(3, All.Float, 0, MakeVertexBuffer(rx, ry, rw, rh)); GL.TexCoordPointer(2, All.Float, 0, MakeFullSizeUVBuffer()); GL.DrawArrays(All.TriangleStrip, 0, 4); // テクスチャを有効に戻す GL.Enable((All)EnableCap.Texture2D); }

テクスチャ描画

C#

public void DrawTexture(int id, float _x, float _y, float _w, float _h, bool isReverse, bool isAbsPos) { int rx, ry; // 絶対座標かの判断 if (isAbsPos) { rx = (int)(_x); ry = (int)(_y); } else { rx = (int)(((_x - (mWidth / 2)) * mScreenScale) + (mWidth / 2)); ry = (int)(((_y - (mHeight / 2)) * mScreenScale) + (mHeight / 2)); } int rw = (int)((_w * mScreenScale)); int rh = (int)((_h * mScreenScale)); int[] tempRect = new int[_XYWH]; tempRect[_X] = mTextureSize[id, _X]; tempRect[_Y] = mTextureSize[id, _Y]; tempRect[_W] = mTextureSize[id, _W]; tempRect[_H] = mTextureSize[id, _H]; // 左右反転処理 if (isReverse) { tempRect[_X] = tempRect[_W]; tempRect[_W] *= -1; } // 切り出しサイズを設定 GL.TexParameterx(All.Texture2D, All.TextureCropRectOes, tempRect); // 実描画 GL.Oes.DrawTex(rx, (mHeight - (ry + rh)), 0, rw, rh); }

頂点バッファ、UVバッファの生成

C#

public float[] MakeVertexBuffer(int _x, int _y, int _w, int _h) { //ウィンドウ座標を正規化デバイス座標に変換 float left = ((float)_x / (float)mWidth ) * 2.0f - 1.0f; float top = ((float)_y / (float)mHeight) * 2.0f - 1.0f; float right = ((float)(_x + _w) / (float)mWidth ) * 2.0f - 1.0f; float bottom = ((float)(_y + _h) / (float)mHeight) * 2.0f - 1.0f; // 頂点バッファの生成 float[] vertexs = { left, top, 0.0f, //頂点0 left, bottom, 0.0f, //頂点1 right, top, 0.0f, //頂点2 right, bottom, 0.0f, //頂点3 }; return MakeFloatBuffer(vertexs); } public float[] MakeFullSizeUVBuffer() { float[] fullSize = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; return MakeUVBuffer(fullSize); } public float[] MakeUVBuffer(float[] uv) { return MakeFloatBuffer(uv); } public float[] MakeFloatBuffer(float[] array) { return (array); }

詳細

使用しているのは、OpenTK ES1.1です。
これらの元になるソースはAndroidでのOpenGLで基本的に動作した物で、それを移植した物になります。

なお、描画処理本体の『黄色でクリア』の部分までは正常に動作しており、背景は黄色で塗りつぶされています。
必要でしたら、バッファの生成の箇所もアップいたします。

iOSでの詳細な作法が解っていないため、足りない設定などがありましたら、ご指摘をよろしくお願いします。

補足

本プロジェクトは、ES1.1で制作することが前提となっています。

追記 テクスチャのバインド処理

C#

public void BindTexture(int id) { GL.BindTexture(All.Texture2D, mTextureID[id]); }

追記 バッファ及びテクスチャの初期化

C#

public void CreateBuffer() { BackgroundColor = UIColor.Blue; CGRect size = UIScreen.MainScreen.Bounds; mWidth = (int)size.Width; mHeight = (int)size.Height; CAEAGLLayer layer = (CAEAGLLayer)Layer; layer.Opaque = true; // コンテキストの取得 mContext = new EAGLContext(EAGLRenderingAPI.OpenGLES1); EAGLContext.SetCurrentContext(mContext); GL.MatrixMode(All.Projection); GL.LoadIdentity(); // ビューポートの設定 GL.Viewport(0, 0, mWidth, mHeight); GL.Scale(1.0f, -1.0f, 1.0f); // Y軸を反転させる GL.Enable((All)EnableCap.Texture2D); GL.Enable((All)EnableCap.AlphaTest); GL.Enable((All)EnableCap.Blend); GL.EnableClientState(All.VertexArray); GL.EnableClientState(All.TextureCoordArray); // カリング処理の設定 GL.Disable((All)EnableCap.CullFace); GL.FrontFace((All)FrontFaceDirection.Cw); // 描画バッファの設定 GL.Oes.GenFramebuffers(1, out mFrameBuffer); GL.Oes.BindFramebuffer(All.FramebufferOes, mFrameBuffer); GL.Oes.GenRenderbuffers(1, out mRenderBuffer); GL.Oes.BindRenderbuffer(All.RenderbufferOes, mRenderBuffer); GL.Oes.GetRenderbufferParameter(All.RenderbufferOes, All.RenderbufferWidthOes, out mWidth); GL.Oes.GetRenderbufferParameter(All.RenderbufferOes, All.RenderbufferHeightOes, out mHeight); mContext.RenderBufferStorage((uint)All.RenderbufferOes, layer); GL.Oes.FramebufferRenderbuffer(All.FramebufferOes, All.ColorAttachment0Oes, All.RenderbufferOes, mRenderBuffer); UIImage image = new UIImage("t_title_logo"); // "t_title_logo"はpngイメージ UIImage[] ImageList = new UIImage[1]; ImageList[0] = image; InitTexture(ImageList, 0, 1); }

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

f-miyu

2020/10/28 09:42

具体的に問題となっていることは何なのでしょうか?どうなれば正常なのでしょうか?
JpTomari

2020/10/28 10:11

言葉足らずで申し訳ありません…。 現状では、背景の黄色で画面いっぱいが塗りつぶされている状態です。 本来想定している動作としては、左上原点で0,0から、100,100(pixel)の赤色矩形が描かれること。 また、その上にかぶせられる形で、0,0の座標にテクスチャ画像が貼られる形になるように組んだつもりです。 求める動作としましては、上記の動作が想定通りに行われることになります。 本プログラムでは、先の矩形並びにテクスチャ画像が全く表示されていない状態ですので、これを修正するための方策をご教授願えればと考えております。
JpTomari

2020/10/28 10:13

もう一つ、修正です。 テクスチャ画像は、一種のスプライト的な扱いになります。 赤い矩形ポリゴンとは別物になりますので、ご注意ください。
f-miyu

2020/10/28 12:03

LayoutSubviewsのBindTexture(0)はどういう処理でしょうか?
JpTomari

2020/10/28 12:33

先ほど追記いたしました。 現時点では、BindTextureを呼んでいるだけのメソッドです。
JpTomari

2020/10/29 04:41

ご指摘ありがとうございます。 ただ、今回頂いた修正箇所を置き換えてみたのですが、やはり上手く動作してくれません…。 他の箇所でのEnable系の設定などで何か過不足がないか、バッファ及びテクスチャ初期化の箇所も追記いたしますので、もしよろしければご確認ください。
f-miyu

2020/10/29 05:15

追記しました。
JpTomari

2020/10/29 05:27

テクスチャの初期化についてもご指摘の通り修正しましたが、何も描画されませんでした。 質問ばかりで恐縮ですが、フレームバッファやレンダバッファの使用方法はこれで正しいのでしょうか?
f-miyu

2020/10/29 05:40

ViewWillAppearでCreateBufferを実行しているなら問題ないと思うのですが。何も描画されないというのは、背景も何も描画されないということでしょうか?後、何かエラーなども出てないでしょうか?
JpTomari

2020/10/29 06:11

たった今自己解決いたしました。 問題は描画周りではなく、それぞれ別の部分で想定外の挙動があったためでした。 1:ポリゴン描画について ポリゴン描画処理内の変数計算において、画面幅のクラス内変数を利用していたが、それが GL.Oes.GetRenderbufferParameterでの指定において内容が破壊されていたため、計算値がエラーとなっていた。 2:テクスチャ描画 テクスチャ画像のサイズが、2の累乗倍に納まっていなかった。 以上が問題の解決方法になります。 前回に引き続き、骨を折っていただき、本当に感謝いたします。 今回も指摘がなければ、澪としていた箇所でしたので、今後は注意深くデバッガで追うよう心がけます。 ありがとうございました!

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

OpenGL ES

携帯電話のような組込み機器のためにデザインされたOpenGLのサブセットです。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xamarin

Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。