VAOをレンダリングさせることができないようです...誰かが私が間違ったことを確認するのを手伝ってくれますか?

WolfHybrid23

この問題の興味深い点は、RenderDocを使おうとしたのですが、キャプチャしたフレームを読み込もとするとRenderDocがクラッシュしました。これは試行するたびに発生したため、この状況ではグラフィックデバッグツールが役に立たないようです...

私はC#と、CSGL(https://github.com/ThatOneCheetah/CSGLと呼ばれるOpenGLおよびGLFWバインディングの素晴らしいセットを使用しています

これが私のレンダリングコードです(私のゲームはグラフィックベースとして手続き型の単色の長方形を使用しています。以下のクラスはすべての描画呼び出しをバッチ処理することを目的としています)。

using System;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

using static CSGL.OpenGL;

namespace BoxBlight
{
    class BoxRenderer
    {
        public const int MAX_RECTANGLES = 500;
        static Rectangle[] rectangles = new Rectangle[MAX_RECTANGLES];
        static int index = 0;

        static uint VAO = 250;
        static uint VBO = 250;
        static uint CBO = 250;

        static bool err = false;

        const string vertShader = @"
#version 150
in  vec3 in_Position;
in  vec4 in_Color;
out vec4 ex_Color;

void main(void) {
    gl_Position = vec4(in_Position.x, in_Position.y, in_Position.z, 1.0);
    ex_Color = in_Color;
}
";

        const string fragShader = @"
#version 150
precision highp float;

in  vec4 ex_Color;
out vec4 gl_FragColor;

void main(void) {
    gl_FragColor = ex_Color;
}
";

        static uint shaderProg = 250;
        static uint vs = 0;
        static uint fs = 0;

        public static void draw(Rectangle rectangle, int offsetX, int offsetY)
        {
            Rectangle r2 = new Rectangle(rectangle);
            r2.x += offsetX;
            r2.y += offsetY;
            rectangles[index++] = r2;
        }

        public static void init()
        {

            if (VAO == 250)
            {
                glGenVertexArrays(1, ref VAO);
            }

            if (VBO == 250)
            {
                glGenBuffers(1, ref VBO);
            }

            if (CBO == 250)
            {
                glGenBuffers(1, ref CBO);
            }

            if (shaderProg == 250)
            {
                shaderProg = glCreateProgram();

                uint vertShd = glCreateShader(GL_VERTEX_SHADER);

                IntPtr str = Marshal.AllocHGlobal(vertShader.Length);
                Marshal.Copy(Encoding.ASCII.GetBytes(vertShader), 0, str, vertShader.Length);

                int length = vertShader.Length;

                glShaderSource(vertShd, 1, ref str, ref length);
                glCompileShader(vertShd);

                Marshal.FreeHGlobal(str);

                int isCompiled = 0;

                glGetShaderiv(vertShd, GL_COMPILE_STATUS, ref isCompiled);

                if (isCompiled == 0)
                {
                    int loglen = 0;
                    glGetShaderiv(vertShd, GL_INFO_LOG_LENGTH, ref loglen);

                    IntPtr log = Marshal.AllocHGlobal(loglen);

                    glGetShaderInfoLog(vertShd, loglen, ref loglen, log);

                    char[] chrs = new char[loglen];
                    string logs = "";
                    Marshal.Copy(log, chrs, 0, loglen);
                    logs.Concat(chrs.AsEnumerable());
                    Marshal.FreeHGlobal(log);
                    Console.Error.WriteLine(logs);

                    err = true;
                    return;
                }

                uint fragShd = glCreateShader(GL_FRAGMENT_SHADER);

                str = Marshal.AllocHGlobal(fragShader.Length);
                Marshal.Copy(Encoding.ASCII.GetBytes(fragShader), 0, str, fragShader.Length);

                length = fragShader.Length;

                glShaderSource(fragShd, 1, ref str, ref length);
                glCompileShader(fragShd);

                Marshal.FreeHGlobal(str);

                isCompiled = 0;

                glGetShaderiv(fragShd, GL_COMPILE_STATUS, ref isCompiled);

                if (isCompiled == 0)
                {
                    int loglen = 0;
                    glGetShaderiv(fragShd, GL_INFO_LOG_LENGTH, ref loglen);

                    IntPtr log = Marshal.AllocHGlobal(loglen);

                    glGetShaderInfoLog(fragShd, loglen, ref loglen, log);

                    char[] chrs = new char[loglen];
                    string logs = "";
                    Marshal.Copy(log, chrs, 0, loglen);
                    logs.Concat(chrs.AsEnumerable());
                    Marshal.FreeHGlobal(log);
                    Console.Error.WriteLine(logs);

                    err = true;
                    return;
                }

                glAttachShader(shaderProg, vertShd);
                glAttachShader(shaderProg, fragShd);

                glLinkProgram(shaderProg);

                int isLinked = 0;

                glGetProgramiv(shaderProg, GL_LINK_STATUS, ref isLinked);
                if (isLinked == 0)
                {
                    int loglen = 0;
                    glGetProgramiv(shaderProg, GL_INFO_LOG_LENGTH, ref loglen);

                    IntPtr log = Marshal.AllocHGlobal(loglen);

                    glGetProgramInfoLog(shaderProg, loglen, ref loglen, log);

                    char[] chrs = new char[loglen];
                    string logs = "";
                    Marshal.Copy(log, chrs, 0, loglen);
                    logs.Concat(chrs.AsEnumerable());
                    Marshal.FreeHGlobal(log);
                    Console.Error.WriteLine(logs);

                    err = true;
                    return;
                }

                vs = vertShd;
                fs = fragShd;
            }
        }

        public static void flush(int xoffset, int yoffset, Rectangle camera)
        {
            if (err)
            {
                index = 0;
                return;
            }

            double[] verts = new double[index * 18];
            double[] colrs = new double[index * 24];

            int indecies = 0;

            for(int i = 0; i < index; i++)
            {
                Rectangle rect = rectangles[i];

                rect.x += xoffset;
                rect.y += yoffset;

                if(camera.Intersects(rect))
                {
                    double x1, y1, x2, y2;
                    x1 = (double)rect.x / camera.w * 2 - 1;
                    x2 = ((double)rect.x + rect.w) / camera.w * 2 - 1;
                    y1 = (1 - (double)rect.y / camera.h) * 2 - 1;
                    y2 = (1 - ((double)rect.y + rect.h) / camera.h) * 2 - 1;

                    verts[i * 18 + 0 ] = x1;
                    verts[i * 18 + 1 ] = y1;
                    verts[i * 18 + 2 ] = 1;

                    verts[i * 18 + 3 ] = x2;
                    verts[i * 18 + 4 ] = y1;
                    verts[i * 18 + 5 ] = 1;

                    verts[i * 18 + 6 ] = x1;
                    verts[i * 18 + 7 ] = y2;
                    verts[i * 18 + 8 ] = 1;

                    verts[i * 18 + 9 ] = x2;
                    verts[i * 18 + 10] = y1;
                    verts[i * 18 + 11] = 1;

                    verts[i * 18 + 12] = x1;
                    verts[i * 18 + 13] = y2;
                    verts[i * 18 + 14] = 1;

                    verts[i * 18 + 15] = x1;
                    verts[i * 18 + 16] = y2;
                    verts[i * 18 + 17] = 1;

                    for (int j = 0; j < 6; j++)
                    {
                        colrs[i * 24 + j * 4 + 0] = (double)rect.c.R / 255;
                        colrs[i * 24 + j * 4 + 1] = (double)rect.c.G / 255;
                        colrs[i * 24 + j * 4 + 2] = (double)rect.c.B / 255;
                        colrs[i * 24 + j * 4 + 3] = (double)rect.c.A / 255;
                    }

                    indecies += 6;
                }
            }

            glBindVertexArray(VAO);

            IntPtr data0 = Marshal.AllocHGlobal(verts.Length * sizeof(double));
            Marshal.Copy(verts, 0, data0, verts.Length);

            glBindBuffer(GL_VERTEX_ARRAY, VBO);
            glBufferData(GL_VERTEX_ARRAY, verts.Length * sizeof(double), data0, GL_DYNAMIC_DRAW);

            glEnableVertexAttribArray(VBO);
            glVertexAttribPointer(VBO, 3, GL_DOUBLE, GL_FALSE, 0, IntPtr.Zero);

            IntPtr data1 = Marshal.AllocHGlobal(colrs.Length * sizeof(double));
            Marshal.Copy(colrs, 0, data1, colrs.Length);

            glBindBuffer(GL_VERTEX_ARRAY, CBO);
            glBufferData(GL_VERTEX_ARRAY, colrs.Length * sizeof(double), data1, GL_DYNAMIC_DRAW);

            glEnableVertexAttribArray(CBO);
            glVertexAttribPointer(CBO, 4, GL_DOUBLE, GL_FALSE, 0, IntPtr.Zero);

            glUseProgram(shaderProg);
            glBindAttribLocation(shaderProg, VBO, "in_Position");
            glBindAttribLocation(shaderProg, CBO, "in_Color");

            glDrawArrays(GL_TRIANGLES, 0, indecies);
            glFlush();

            Marshal.FreeHGlobal(data0);
            Marshal.FreeHGlobal(data1);

            glUseProgram(0);
            glDisableVertexAttribArray(VBO);
            glDisableVertexAttribArray(CBO);

            index = 0;
            rectangles = new Rectangle[MAX_RECTANGLES];
        }

        public static void clean()
        {
            glDetachShader(shaderProg, vs);
            glDetachShader(shaderProg, fs);

            glDeleteProgram(shaderProg);

            glDeleteShader(vs);
            glDeleteShader(fs);

            glDeleteBuffers(1, ref VBO);
            glDeleteBuffers(1, ref CBO);

            glDeleteVertexArrays(1, ref VAO);

            rectangles = new Rectangle[0];
            index = 0;
            err = true;
        }
    }
}

これが私のメインのゲームクラスです:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static CSGL.CSGL;
using static CSGL.OpenGL;
using static CSGL.Glfw3;
using System.Drawing;

namespace BoxBlight
{
    class Program
    {
        public static IntPtr window = IntPtr.Zero;
        public static bool running = true;
        public const long FPS = 60;

        public static long CurrentTimeMS { get => DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; }

        static void Main(string[] args)
        {
            csglLoadGlfw();

            if(glfwInit() != GLFW_TRUE)
            {
                Console.Error.WriteLine("Failed to initialize GLFW!");
            }

            glfwDefaultWindowHints();
            window = glfwCreateWindow(1024, 768, "Box Blight (v1.0.0)", IntPtr.Zero, IntPtr.Zero);

            if(window == IntPtr.Zero)
            {
                Console.Error.WriteLine("Failed to create window!");
            }

            glfwMakeContextCurrent(window);

            csglLoadGL();
            glInitNames();

            long lastTime = CurrentTimeMS;

            glViewport(0, 0, 1024, 768);

            BoxRenderer.init();

            while(running)
            {
                glOrtho(0, 1024, 768, 0, 0.1, 3);

                BoxRenderer.draw(new Rectangle(0, 0, 1024, 768, Color.HotPink), 0, 0);
                BoxRenderer.draw(new Rectangle(16, 16, 16, 16, Color.White), 0, 0);

                BoxRenderer.flush(0, 0, new Rectangle(0, 0, 1024, 768, Color.Black));

                glfwSwapBuffers(window);
                glfwPollEvents();

                while (lastTime + FPS / 1000 > CurrentTimeMS) ;
            }

            BoxRenderer.clean();

            glfwTerminate();
        }
    }
}
Rabbid76

のパラメータはglVertexAttribPointerそれぞれglEnableVertexAttribArray、バッファオブジェクトではなく属性インデックスです。汎用頂点属性データの配列が生成されるとき、バッファオブジェクトは現在のバッファオブジェクトである必要があります(バインドされている必要があります)。属性インデックスはglGetAttribLocation、リンクされたプログラムオブジェクトから取得できます。頂点配列バッファーのターゲットはGL_ARRAY_BUFFERはありませんGL_VERTEX_ARRAYGL_VERTEX_ARRAYは、レガシーOpenGL固定関数属性の機能状態を指定し、有効なバッファーターゲットではありません)。

int vertex_index = glGetAttribLocation(shaderProg, "in_Position");
int color_index  = glGetAttribLocation(shaderProg, "in_Color");

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, verts.Length * sizeof(double), data0, GL_DYNAMIC_DRAW);

glEnableVertexAttribArray(vertex_index);
glVertexAttribPointer(vertex_index, 3, GL_DOUBLE, GL_FALSE, 0, IntPtr.Zero);

glBindBuffer(GL_ARRAY_BUFFER, CBO);
glBufferData(GL_ARRAY_BUFFER, colrs.Length * sizeof(double), data1, GL_DYNAMIC_DRAW);

glEnableVertexAttribArray(color_index);
glVertexAttribPointer(color_index, 4, GL_DOUBLE, GL_FALSE, 0, IntPtr.Zero);

によって属性インデックスを設定することは可能ですglBindAttribLocationが、これはプログラムがリンクされる前に行う必要があることに注意してください属性インデックスはプログラムリソースであり、プログラムがリンクされた後で変更することはできません。さらに、属性インデックスはバッファオブジェクトではありません。バッファと属性インデックスは、glVertexAttribPointerが呼び出されると関連付けられ頂点配列オブジェクトの状態ベクトルに格納されます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ