Как правильно визуализировать сетки в отдельных объектах массива opengl? - PullRequest
0 голосов
/ 03 января 2019

Я пытаюсь визуализировать два треугольника, используя отдельные объекты Vertex Array. Я использую OpenTK на C # (он предоставляет почти тот же API по сравнению с определенным API OpenGL). Вот мой код:

Я начинаю с объявления моих переменных.

    public partial class Form1 : Form
{
    public Form1() {
        InitializeComponent();
    }
    bool loaded = false; //do not use glcontrol before it is not loaded
    private uint VAO1; 
    private uint object1_vertex_buffer; private uint object1_vertices_size; private uint object1_index_buffer;
    private uint object2_vertex_buffer; private uint object2_vertices_size; private uint object2_index_buffer;
    private uint VAO2;
    private uint VBO;
    int VertexShader;
    int FragmentShader;
    int ShaderProgram;
    private float[] object1_vertices = new float[] {
       -0.2f, 0.0f, 0.0f, 
        0.2f, 0.0f, 0.0f, 
        0.0f, 0.2f, 0.0f
    };
    private float[] object2_vertices = new float[] {
        -0.5f, 0.0f, 0.0f,
        0.5f, 0.0f, 0.0f,
        0.0f, 0.4f, 0.0f
    };
    private int[] object1_indices = new int[] { 0, 1, 2 };
    private int[] object2_indices = new int[] { 0, 1, 2 };

Здесь я рисую каждый кадр:

    private void glControl1_Paint(object sender, PaintEventArgs e)
    {
        if (!loaded)//<--------------------------------------
            return;//<--------------------------------------
        // Clear the color buffer.
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        GL.UseProgram(ShaderProgram);
        // Object 1
        GL.BindVertexArray(VAO1);
        // drawelements requires count of elements, not bytes
        GL.DrawElements(PrimitiveType.Triangles, object1_indices.Length, DrawElementsType.UnsignedInt, 0);

        // Object 2
        GL.BindVertexArray(VAO2);
        GL.DrawElements(PrimitiveType.Triangles, object2_indices.Length, DrawElementsType.UnsignedInt, 0);

       ErrorCode miauw = GL.GetError(); /// AND I GET HERE NO ERROR!
        /// at the end I have a screen filled by a background color, which is set in GL.ClearColor()
        glControl1.SwapBuffers();
    }

Здесь я делаю инициализацию массивов и буферов OpenGL. Я начинаю здесь два объекта Vertex Array (по одному для каждого треугольника) и два буфера (для каждого): вершины и индексы. Я установил правильную длину в байтах для них

    private void glControl1_Load(object sender, EventArgs e) {
        loaded = true;
        GL.ClearColor(Color.SkyBlue);
        GL.Enable(EnableCap.DepthTest);
        GL.DepthFunc(DepthFunction.Less);

        // Load the source of the vertex shader and compile it.
        VertexShader = GL.CreateShader(ShaderType.VertexShader);
        GL.ShaderSource(VertexShader, MyOpenglThings.VertexShaderSource);
        GL.CompileShader(VertexShader);

        // Load the source of the fragment shader and compile it.
        FragmentShader = GL.CreateShader(ShaderType.FragmentShader);
        GL.ShaderSource(FragmentShader, MyOpenglThings.FragmentShaderSource);
        GL.CompileShader(FragmentShader);

        // Create the shader program, attach the vertex and fragment shaders and link the program.
        ShaderProgram = GL.CreateProgram();
        GL.AttachShader(ShaderProgram, VertexShader);
        GL.AttachShader(ShaderProgram, FragmentShader);
        GL.LinkProgram(ShaderProgram);


        // https://stackoverflow.com/questions/34068792/drawing-multiple-objects-in-opengl-with-different-buffers
        // https://stackoverflow.com/questions/34072056/rendering-two-objects-with-opengl-and-vertex-array-objects
        GL.GenVertexArrays(1, out VAO1);
        GL.BindVertexArray(VAO1);
        GL.GenVertexArrays(1, out VAO2);
        GL.BindVertexArray(VAO2);

        // Object 1 vertex positions
        GL.GenBuffers(1, out object1_vertex_buffer);
        GL.BindBuffer(BufferTarget.ArrayBuffer, object1_vertex_buffer);
        GL.BufferData(BufferTarget.ArrayBuffer, object1_vertices.Length * sizeof(float), object1_vertices,BufferUsageHint.StaticDraw);
        GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
        // Object 1 vertex indices
        GL.GenBuffers(1, out object1_index_buffer);
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, object1_index_buffer);
        GL.BufferData(BufferTarget.ElementArrayBuffer, object1_indices.Length * sizeof(int), object1_indices, BufferUsageHint.StaticDraw);

        GL.BindVertexArray(VAO2);
        // Object 2 vertex positions
        GL.GenBuffers(1, out object2_vertex_buffer);
        GL.BindBuffer(BufferTarget.ArrayBuffer, object2_vertex_buffer);
        GL.BufferData(BufferTarget.ArrayBuffer, object2_vertices.Length * sizeof(float), object2_vertices, BufferUsageHint.StaticDraw);
        GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
        // Object 2 vertex indices
        GL.GenBuffers(1, out object2_index_buffer);
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, object2_index_buffer);
        GL.BufferData(BufferTarget.ElementArrayBuffer, object2_indices.Length*sizeof(int), object2_indices, BufferUsageHint.StaticDraw);

    }

Я освобождаю выделенные ресурсы opengl (это не относится к моему вопросу, оно даже сейчас не вызывается хе)

    private void CleanupOpenGL() {
          // ...
    }

}

Я скопировал коды шейдеров:

class MyOpenglThings
{

    // A simple vertex shader possible. Just passes through the position vector.
    public const string VertexShaderSource = @"
        #version 330
        layout(location = 0) in vec4 position;
        void main(void)
        {
            gl_Position = position;
        }
    ";

    // A simple fragment shader. Just a constant red color.
    public const string FragmentShaderSource = @"
        #version 330
        out vec4 outputColor;
        void main(void)
        {
            outputColor = vec4(1.0, 0.0, 0.0, 1.0);
        }
    ";
}

Но когда я запускаю программу, я получаю только окно, заполненное SkyBlue Color. По крайней мере, opengl способен отображать цвет фона. Но я тоже хочу получить два красных треугольника.

Что там не так? Как получить рендеринг двух сеток в объектах Vertex Array?

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Ответ выше действительно помог. (Я публикую здесь, потому что комментарий не подходит к коду.) Итак, мой код загрузки теперь выглядит так:

        private void glControl1_Load(object sender, EventArgs e) {
        loaded = true;
        GL.ClearColor(Color.SkyBlue);
        GL.Enable(EnableCap.DepthTest);
        GL.DepthFunc(DepthFunction.Less);

        // Load the source of the vertex shader and compile it.
            // ....
        // Load the source of the fragment shader and compile it.
            // ....
        // Create the shader program, attach the vertex and fragment shaders and link the program.
            // ....
        GL.GenVertexArrays(1, out VAO1);
        GL.BindVertexArray(VAO1);

        // Object 1 vertex positions
        GL.GenBuffers(1, out object1_vertex_buffer);
        GL.BindBuffer(BufferTarget.ArrayBuffer, object1_vertex_buffer);
        GL.BufferData(BufferTarget.ArrayBuffer, object1_vertices.Length * sizeof(float), object1_vertices,BufferUsageHint.StaticDraw);
        GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
        GL.EnableVertexAttribArray(0);
        // Object 1 vertex indices
        GL.GenBuffers(1, out object1_index_buffer);
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, object1_index_buffer);
        GL.BufferData(BufferTarget.ElementArrayBuffer, object1_indices.Length * sizeof(int), object1_indices, BufferUsageHint.StaticDraw);

        GL.GenVertexArrays(1, out VAO2);
        GL.BindVertexArray(VAO2);
        // Object 2 vertex positions
        GL.GenBuffers(1, out object2_vertex_buffer);
        GL.BindBuffer(BufferTarget.ArrayBuffer, object2_vertex_buffer);
        GL.BufferData(BufferTarget.ArrayBuffer, object2_vertices.Length * sizeof(float), object2_vertices, BufferUsageHint.StaticDraw);
        GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
        GL.EnableVertexAttribArray(0);
        // Object 2 vertex indices
        GL.GenBuffers(1, out object2_index_buffer);
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, object2_index_buffer);
        GL.BufferData(BufferTarget.ElementArrayBuffer, object2_indices.Length*sizeof(int), object2_indices, BufferUsageHint.StaticDraw);

    }

параметр GL.EnableVertexAttribArray должен соответствовать значению в шейдерной программе.

Также изменились немного геометрические координаты, потому что треугольники раньше перекрывались.

0 голосов
/ 03 января 2019

Когда вы определяете массив общих данных атрибута вершины (GL.VertexAttribPointer), объект массива Vertex , в котором должно храниться определение, должен быть связан.
Это относится к спецификации VAO2, но не к VAO1, потому что после

GL.GenVertexArrays(1, out VAO1);
GL.BindVertexArray(VAO1);
GL.GenVertexArrays(1, out VAO2);
GL.BindVertexArray(VAO2);

объект массива вершин VAO2 связан.

Кроме того, общий массив атрибутов вершин должен быть включен с помощью GL.EnableVertexAttribArray. Состояние, если массив вершин включен или отключен, сохраняется и в объекте массива вершин:

GL.GenVertexArrays(1, out VAO1);
GL.BindVertexArray(VAO1);

// Object 1 vertex positions
GL.GenBuffers(1, out object1_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object1_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object1_vertices.Length * sizeof(float), object1_vertices,BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
// [...]

GL.GenVertexArrays(1, out VAO2);
GL.BindVertexArray(VAO2);

// Object 2 vertex positions
GL.GenBuffers(1, out object2_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object2_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object2_vertices.Length * sizeof(float), object2_vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
// [...]
...