Bagaimana cara agar instance berfungsi di program OpenGL saya?

https://pastebin.com/Dyv5JBFd

Saya membuat array simpul untuk kubus saya. Saya mencoba membuat 1000 kubus dalam bentuk kubus. Saya yakin saya tidak memahami kapan harus membuat dan mengikat VAO dan VBO. Saya tidak tahu informasi apa yang dapat membantu memecahkan masalah ini. Di pastebin saya memasukkan shader terlebih dahulu dan kemudian kode utama. Tidak ada yang muncul, tapi sedang berjalan.

Sunting: kubus ada di baris 100

Sunting 2: kode instan dimulai pada 160

Sunting 3: matriks tampilan mulai dari 272

Sunting 4: panggilan undian dimulai pada 293

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 2) in mat4 instanceMatrix;

uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * instanceMatrix * vec4(aPos, 1.0f);
}
#include <glew.h>
#include <glfw3.h>
#include <iostream>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>

#include "Shaders/Functions/loadShader.h"
#include "Camera.h"
#include "Input/Input.h"

//Function used to resize the window appropriately.
void FrameBufferSizeCallback(GLFWwindow* window, int width, int height);
inline void Mouse(GLFWwindow* window, double xPos, double yPos);

//Global screen settings.
const unsigned int SCR_WIDTH  = 800;
const unsigned int SCR_HEIGHT = 600;

//Global camera variables.
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));

//Global timing variables.
float deltaTime = 0.0f;         //Time difference of current frame and last frame.
float lastTime = 0.0f;         //Keeps track of the time of the last frame. Used to calculate deltaTime.

int main(void)
{
    /* Initialize the library */
    if (!glfwInit())
    {
        std::cout << "GLFW initialization failed." << std::endl;
        return -1;
    }

    /*       OpenGLtutorials.org tutorial       */
    //Triangle doesn't show if other 3 are uncommented
    glfwWindowHint(GLFW_SAMPLES, 4);                                    //4x antialiasing
    //glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);                      //OpenGL 3.3
    //glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);      //We don't want the old OpenGL
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    /*       OpenGLtutorials.org tutorial end       */

    GLFWwindow* window;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(1280, 1024, "Window of the Gods!", NULL, NULL);
   
    if (!window)
    {
        glfwTerminate();
        std::cout << "GLFW window creation failed." << std::endl;
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    //Added code
    glfwSetFramebufferSizeCallback(window, FrameBufferSizeCallback);
    glfwSetCursorPosCallback(window, Mouse);

    //Tells GLFW to capture our mouse.
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

    //Check if GLEW is initialized
    if (glewInit() != GLEW_OK)
    {
        std::cout << "GLEW failed to initialize." << std::endl;
    }

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    //Compile and load shaders and store the program id
    GLuint programID = LoadShaders("Shaders/Vertex/CameraShader.vert", "Shaders/Fragment/SimpleFragmentShader.frag");

    //Prints the GLEW and openGL versions
    std::cout << "Using GLEW version :" << glewGetString(GLEW_VERSION) << std::endl;
    std::cout << "Using openGL version: " << glGetString(GL_VERSION) << std::endl;

    /*
      *******CUBE*******
      An array of 3 vectors which represents 3 vertices; 6 to make a rectangle; Each segment represents a face of a cube, made of two triangles;
      Looking at the face, the first vertex of each triangle is top left, triangle formed counter-clockwise; First vertex on top is (-0.5, 0.5, -0.5);
      First vertex on bottom is (-0.5, -0.5, 0.5);
   
        1         3
      4    
             
               
                  2
      5         6
    */
    static const GLfloat cubeVertexBuffer[] =
    {
         //Front
        -0.5f,  0.5f,  0.5f,
         0.5f, -0.5f,  0.5f,
         0.5f,  0.5f,  0.5f,
        -0.5f,  0.5f,  0.5f,
        -0.5f, -0.5f,  0.5f,
         0.5f, -0.5f,  0.5f,
         //Right
         0.5f,  0.5f,  0.5f,
         0.5f, -0.5f, -0.5f,
         0.5f,  0.5f, -0.5f,
         0.5f,  0.5f,  0.5f,
         0.5f, -0.5f,  0.5f,
         0.5f, -0.5f, -0.5f,
         //Back
         0.5f,  0.5f, -0.5f,
        -0.5f, -0.5f, -0.5f,
        -0.5f,  0.5f, -0.5f,
         0.5f,  0.5f, -0.5f,
         0.5f, -0.5f, -0.5f,
        -0.5f, -0.5f, -0.5f,
         //Left
        -0.5f,  0.5f, -0.5f,
        -0.5f, -0.5f,  0.5f,
        -0.5f,  0.5f,  0.5f,
        -0.5f,  0.5f, -0.5f,
        -0.5f, -0.5f, -0.5f,
        -0.5f, -0.5f,  0.5f,
         //Top
        -0.5f,  0.5f, -0.5f,
         0.5f,  0.5f,  0.5f,
         0.5f,  0.5f, -0.5f,
        -0.5f,  0.5f, -0.5f,
        -0.5f,  0.5f,  0.5f,
         0.5f,  0.5f,  0.5f,
         //Bottom
        -0.5f, -0.5f,  0.5f,
         0.5f, -0.5f, -0.5f,
         0.5f, -0.5f,  0.5f,
        -0.5f, -0.5f,  0.5f,
        -0.5f, -0.5f, -0.5f,
         0.5f, -0.5f, -0.5f,
    };

    //World space position of our cube.
    /*glm::vec3 cubePosition[] =
    {  
        glm::vec3( 0.0f,  0.0f,  0.0f),
    };*/

    //INSTANCING TEST
    //Need to do: make sure the coordinates right.
    unsigned int cubeGridXCoord = 10;
    unsigned int cubeGridYCoord = 10;
    unsigned int cubeGridZCoord = 10;
    float displacement = 4.0f;
    unsigned int currentIndex = 0;
    glm::mat4* modelMatrices;

    modelMatrices = new glm::mat4[cubeGridXCoord * cubeGridYCoord * cubeGridZCoord];
    for (unsigned int i = 0; i < cubeGridXCoord; i++)
    {
        for (unsigned int j = 0; j < cubeGridYCoord; j++)
        {
            for (unsigned int k = 0; k < cubeGridZCoord; k++)
            {
                glm::mat4 model = glm::mat4(1.0f);
                model = glm::translate(model, glm::vec3((float)i / displacement, (float)j / displacement, (float)k / displacement));
                model = glm::scale(model, glm::vec3(0.1f));
                modelMatrices[currentIndex++] = model;
            }
        }
    }

    //INSTANCING TEST END

    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    //Identify vertex buffer
    GLuint vertexbuffer;
    //Generate 1 buffer, put the resulting identifier in vertexbuffer
    glGenBuffers(1, &vertexbuffer);

    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    //Give the vertices to OpenGL
    //glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertexBuffer), cubeVertexBuffer, GL_STATIC_DRAW);
    glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertexBuffer), cubeVertexBuffer, GL_STATIC_DRAW);

    //Added code end
    //First attribute buffer : vertices
    glEnableVertexAttribArray(0);
    glVertexAttribPointer
    (
        0,              //attribute 0. No reason 0, but must match layout in shader.
        3,              //size
        GL_FLOAT,       //type
        GL_FALSE,       //normalized?
        0,              //stride
        (void*)0        //array buffer offset
        );

    glBindVertexArray(0);

    unsigned int matricesBuffer;
    glGenBuffers(1, &matricesBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, matricesBuffer);
    glBufferData(GL_ARRAY_BUFFER, cubeGridXCoord * cubeGridYCoord * cubeGridZCoord * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW);

    glBindVertexArray(VAO);

    // vertex attributes

    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)0);
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(1 * sizeof(glm::vec4)));
    glEnableVertexAttribArray(4);
    glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(2 * sizeof(glm::vec4)));
    glEnableVertexAttribArray(5);
    glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(3 * sizeof(glm::vec4)));

    glVertexAttribDivisor(2, 1);
    glVertexAttribDivisor(3, 1);
    glVertexAttribDivisor(4, 1);
    glVertexAttribDivisor(5, 1);

    glBindVertexArray(0);

    double previousFPSTime = glfwGetTime();
    int frameCount = 0;

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        //Get the time variables and display fps
        float currentTime = glfwGetTime();
        deltaTime = currentTime - lastTime;
        lastTime= currentTime;
        frameCount++;
        if (currentTime - previousFPSTime >= 1.0f)
        {
            std::cout << "FPS: " << frameCount << "\r";
            frameCount = 0;
            previousFPSTime = currentTime;
        }

        //Input
        ProcessInput(window, camera, deltaTime);


        /* Render here */
        glClearColor(0.0f, 0.0f, 0.5f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


        //Added code
        glUseProgram(programID);


        //Pass the projection matrix to shader ( in this case could change every frame )
        glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        glUniformMatrix4fv(glGetUniformLocation(programID, "projection"), 1, GL_FALSE, &projection[0][0]);

        //Camera/view transformation.
        glm::mat4 view = camera.GetViewMatrix();
        glUniformMatrix4fv(glGetUniformLocation(programID, "view"), 1, GL_FALSE, &view[0][0]);
       
        //for (unsigned int i = 0; i < 1000; i++)
        //{
        //    //Calculate model matrix and initialize.
        //    glm::mat4 model = glm::mat4(1.0f);
        //    model = glm::translate(model, cubePosition[0] + glm::vec3(glm::cos(i)* 0.2f + (glm::cos(i)), i * 0.1f, glm::sin(i) * 0.2f + (glm::sin(i))));
        //    //model = glm::rotate(model, glm::radians(0.0f), glm::vec3(1.0f, 0.3f, 0.5f));
        //    model = glm::scale(model, glm::vec3(0.1f));
        //    glUniformMatrix4fv(glGetUniformLocation(programID, "model"), 1, GL_FALSE, &model[0][0]);

        //    //Draw the triangle
        //    glDrawArrays(GL_TRIANGLES, 0, 36); // Starting from vertex 0; 3 vertices = one triangle, 6 = one face, 36 = one cube;
        //}

        glBindVertexArray(VAO);
        glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0, cubeGridXCoord * cubeGridYCoord * cubeGridZCoord);
        glBindVertexArray(0);

        //Added code end

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }
   
    glDisableVertexAttribArray(0);
    glfwTerminate();
    return 0;
}

person Truth7442    schedule 18.06.2020    source sumber
comment
@ Rabbid76 maaf saya rasa itu akan membantu, kepala saya terbentur keyboard. Ini berjalan, dan akan memunculkan jendela, tetapi tidak ada kubus yang muncul.   -  person Truth7442    schedule 18.06.2020
comment
@ rabbid76 kode yang saya komentari bahwa kubus yang dirender berfungsi secara berulang. Jika itu bisa membantu.   -  person Truth7442    schedule 18.06.2020
comment
Jadi situasinya adalah Anda mengomentari kode yang merender kubus, dan sekarang kubus tersebut tidak dirender?   -  person JaMiT    schedule 18.06.2020
comment
@Jamit Ya karena saya mencoba merendernya dengan cara yang berbeda. Saya menggunakan 1000 panggilan undian, dan saya ingin menggunakannya dengan instancing.   -  person Truth7442    schedule 18.06.2020
comment
@Jamit ya saya akan kembali lagi besok, hanya berharap seorang guru akan melihat sesuatu yang jelas atau semacamnya. Terima kasih   -  person Truth7442    schedule 18.06.2020


Jawaban (1)


Cuplikan kode Anda menggambar geometri yang diindeks melalui glDrawElementsInstanced():

        glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0, cubeGridXCoord * cubeGridYCoord * cubeGridZCoord);

tanpa buffer indeks (GL_ELEMENT_ARRAY_BUFFER) terikat.

Entah, glDrawArraysInstanced() harus digunakan sebagai pengganti elemen gambar, atau definisi geometri yang diindeks harus ditambahkan.

Momen mencurigakan lainnya adalah pengikatan 4 array atribut:

    glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)0);
    glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(1 * sizeof(glm::vec4)));
    glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(2 * sizeof(glm::vec4)));
    glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(3 * sizeof(glm::vec4)));

sedangkan program GLSL hanya mendefinisikan satu program saja

layout (location = 2) in mat4 instanceMatrix;

Saya berharap program GLSL akan mendefinisikan 4 atribut vec4 vertex dalam kasus ini dan membuat mat4 dalam kode, tapi saya belum pernah menangani ini sebelumnya (mungkin Anda menggunakan trik yang diterima oleh spesifikasi OpenGL).

person gkv311    schedule 18.06.2020
comment
Anda benar dengan glDrawElementsInstanced/glDrawArraysInstanced. Pokoknya Anda harus menentukan 4 atribut untuk input vertex shader tipe mat4, bagian pertanyaan ini baik-baik saja. - person Rabbid76; 18.06.2020
comment
Terima kasih banyak kawan, saya sudah menunjukkannya sekarang. Ini luar biasa. Sekarang saya perlu mencari cara terbaik untuk memanipulasi kubus individual. Terima kasih lagi! - person Truth7442; 18.06.2020
comment
Berubah dari 10.000 kubus pada 20 fps menjadi 125k pada 70 fps, ini luar biasa. - person Truth7442; 18.06.2020