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

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

ただいまの
回答率

88.60%

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 209

JpTomari

score 1

概要

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

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

変数定義

        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;

描画処理本体

        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)
            {
            }
        }

テクスチャ読み込み

        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);
            }
        }

 

ポリゴン描画

        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);
        }

テクスチャ描画

        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バッファの生成

        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で制作することが前提となっています。

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

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

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

        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ページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

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

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

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

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • JpTomari

    2020/10/29 14:27

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

    キャンセル

  • f-miyu

    2020/10/29 14:40

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

    キャンセル

  • JpTomari

    2020/10/29 15:11

    たった今自己解決いたしました。
    問題は描画周りではなく、それぞれ別の部分で想定外の挙動があったためでした。

    1:ポリゴン描画について
    ポリゴン描画処理内の変数計算において、画面幅のクラス内変数を利用していたが、それが
    GL.Oes.GetRenderbufferParameterでの指定において内容が破壊されていたため、計算値がエラーとなっていた。
    2:テクスチャ描画
    テクスチャ画像のサイズが、2の累乗倍に納まっていなかった。

    以上が問題の解決方法になります。

    前回に引き続き、骨を折っていただき、本当に感謝いたします。
    今回も指摘がなければ、澪としていた箇所でしたので、今後は注意深くデバッガで追うよう心がけます。
    ありがとうございました!

    キャンセル

回答 3

check解決した方法

0

問題は描画周りではなく、それぞれ別の部分で想定外の挙動があったためでした。

1:ポリゴン描画について
ポリゴン描画処理内の変数計算において、画面幅のクラス内変数を利用していたが、それが
GL.Oes.GetRenderbufferParameterでの指定において内容が破壊されていたため、計算値がエラーとなっていた。

2:テクスチャ描画
テクスチャ画像のサイズが、2の累乗倍に納まっていなかった。

以上です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

いろいろ間違っていたので、以下の様に修正しました。

        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.BlendFunc((All)BlendingFactorDest.SrcAlpha, (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);
+               DrawTexture(0, 0, 0, 100, 100, false, false);

                GL.Oes.BindRenderbuffer(All.RenderbufferOes, mRenderBuffer);
                mContext.PresentRenderBuffer((uint)All.RenderbufferOes);
            }
            catch (Exception e)
            {
            }
        }

        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);
+               GL.TexImage2D(All.Texture2D, 0, (int)All.Rgba, mTextureSize[i, _W], -mTextureSize[i, _H], 0, (All)OpenTK.Graphics.ES11.PixelFormat.Rgba, All.UnsignedByte, data.Bytes);
            }
        }

        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.Color4(1.0f, 1.0f, 1.0f, 1.0f);

            // 切り出しサイズを設定
-           GL.TexParameterx(All.Texture2D, All.TextureCropRectOes, tempRect);
+           GL.TexParameter(All.Texture2D, All.TextureCropRectOes, tempRect);

            // 実描画
            GL.Oes.DrawTex(rx, (mHeight - (ry + rh)), 0, rw, rh);
        }

追記

以下の様に修正してみて下さい。

        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 image = UIImage.FromBundle("t_title_logo");  // "t_title_logo"はpngイメージ
            UIImage[] ImageList = new UIImage[1];
            ImageList[0] = image;
            InitTexture(ImageList, 0, 1);
        }

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/10/29 15:17

    なんか、コメントが全部吹っ飛んでますね…。

    ただいま、自己解決できました。
    問題は描画周りではなく、それぞれ別の部分で想定外の挙動があったためでした。

    1:ポリゴン描画について
    ポリゴン描画処理内の変数計算において、画面幅のクラス内変数を利用していたが、それが
    GL.Oes.GetRenderbufferParameterでの指定において内容が破壊されていたため、計算値がエラーとなっていた。

    2:テクスチャ描画
    テクスチャ画像のサイズが、2の累乗倍に納まっていなかった。

    以上です。

    前回に引き続いてのご回答、本当に感謝しております。
    今回もご指摘がなければ、気づかなかった部分も多々ございました。
    今後はもう少し注意深くデバッガで追うように心がけます。
    本当にありがとうございました!

    キャンセル

0

問題は描画周りではなく、それぞれ別の部分で想定外の挙動があったためでした。

1:ポリゴン描画について
ポリゴン描画処理内の変数計算において、画面幅のクラス内変数を利用していたが、それが
GL.Oes.GetRenderbufferParameterでの指定において内容が破壊されていたため、計算値がエラーとなっていた。

2:テクスチャ描画
テクスチャ画像のサイズが、2の累乗倍に納まっていなかった。

以上です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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