OpenGL索引绘图[复制]

fnvucqvd  于 2023-05-17  发布在  其他
关注(0)|答案(1)|浏览(98)

此问题已在此处有答案

What is the result of NULL + int?(4个答案)
8天前关闭
我试图用一个自定义的FragmentShader来绘制一个三角形,以获得三角形的渐变效果。
我试图使用索引绘图而不是绘制数组。
虽然glDrawArrays(...)工作得很好,但glDrawElements(...)不适合我。我只是得到一个空白的屏幕与索引绘图,而不是一个正常的输出(截图如下所附)。
有人能告诉我我哪里做错了吗?

  • 这是我的代码 *
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>

// Vertex Shader source code
const char* vertexShaderSource = 
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aColor;\n"
"out vec3 outColor;\n"
"void main() {\n"
"    gl_Position = vec4(aPos, 1.0);\n"
"    outColor = aColor;\n"
"}\n\0";

// Fragment Shader source code
const char* fragmentShaderSource = 
"#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 outColor;\n"
"void main() {\n"
"    FragColor = vec4(outColor, 1.0f);\n"
"}\n\0";

const int width{ 800 };
const int height{ 600 };

bool WIREFRAME_MODE = false;

int main() {
    glfwInit();

#pragma region Creating a Window

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow* window = glfwCreateWindow(width, height, "Triangle Exercise", nullptr, nullptr);
    if (!window) {
        std::cout << " >> Failed to create window!" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

#pragma endregion 

    gladLoadGL();

    glViewport(0, 0, width, height);

#pragma region Shader Compilation

    // Vertex Shader
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);

    // Fragment Shader
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);

    // Shader Program
    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    // Delete the shaders
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

#pragma endregion 

#pragma region Vertex and Index data

    // Vertex data
    GLfloat vertices[] = {
        // positions            // colors
         0.5f, -0.5f, 0.0f,     1.0f, 0.0f, 0.0f,  // bottom right
        -0.5f, -0.5f, 0.0f,     0.0f, 1.0f, 0.0f,  // bottom left
         0.0f,  0.5f, 0.0f,     0.0f, 0.0f, 1.0f   // top  
    };

    // Index data
    GLuint indices[] = {
        0, 1, 2
    };

#pragma endregion 

#pragma region VAO, VBO and EBO

    GLuint VAO;     // Vertex Attribute Object ref
    GLuint VBO;     // Vertex Buffer Object ref
    GLuint EBO;     // Element Buffer Object ref

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // Point to the X,Y,Z vertex data in the VBO (at layout location 0)
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * (sizeof(GLfloat)), (void*)0);           
    glEnableVertexAttribArray(0);

    // Point to the RGB color data in the VBO (at layout location 1)
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * (sizeof(GLfloat)), (void*)(3*sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, 0);               // unbind VBO
    glBindVertexArray(0);                           // unbind VAO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);       // unbind EBO (conatined in VAO)

#pragma endregion 

    // While window isn't closed
    while (!glfwWindowShouldClose(window)) {

        if (WIREFRAME_MODE) {
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);      // Wireframe mode
        }
        else {
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);      // Fill mode
        }

        glClearColor(0, 0, 0, 1);                           // black background
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);

        // WORKS FINE
        glDrawArrays(GL_TRIANGLES, 0, sizeof(vertices) / sizeof(GLfloat));

        // DOESN'T WORK?
        //
        //glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(GLuint), GL_UNSIGNED_INT, indices);
        //

        glfwSwapBuffers(window);

        glfwPollEvents();
    }

#pragma region Cleanup

    glDeleteProgram(shaderProgram);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &VAO);
    glDeleteBuffers(1, &EBO);
    glfwDestroyWindow(window);

#pragma endregion

    glfwTerminate();
    return 0;
}

使用glDrawArrays()输出屏幕截图:

使用glDrawElements()输出屏幕截图:

我试着检查我的EBO的参数是否错误,但它们对我来说似乎很好。

hlswsv35

hlswsv351#

glDrawElements(“indices”)的最后一个参数不应该是指向indices数组的指针,而是“数组中第一个索引在缓冲区数据存储中的偏移量”(ref),然后转换为GLvoid*。这里,绘制调用应该使用所有3个索引,因此偏移量应该为0:

glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(GLuint), GL_UNSIGNED_INT, static_cast<GLvoid*>(0));

(其他大致等效的表达式也是可能的,诸如0NULLnullptr
这种混淆可能来自this等文档,其中参数被错误地描述为“指向索引存储位置的指针”。我怀疑这就是glDrawElements在旧版OpenGL中的工作方式(例如:OpenGL 1.1),并且由于函数的使用发生了变化,而函数原型保持不变,因此必须将字节偏移转换为空指针。

相关问题