OpenGL尝试渲染立方体,但平面之间有奇怪的线

时间:2019-01-05 17:39:05

标签: c++ opengl rendering coordinate-transformation

多维数据集渲染

嘿,我认为我如何将数据发送到顶点或使用GL_CCW对索引进行排序的方式可能有误

struct Vertex
{
    glm::vec3 position;
    glm::vec3 color;
    glm::vec3 normal;
};

使用Vertex结构的顶点

Vertex vertices[] =
{   
/*FRONT SQUARE*/
    ///BOTTOM LEFT
glm::vec3(-0.5f, -0.5f, 1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),

    ///bottom RIGHT
    glm::vec3(0.5f, -0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
    ////TOP RIGHT
    glm::vec3(0.5f, 0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
    ///TOP LEFT
    glm::vec3(-0.5f, 0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),

    ///BOTTOM LEFT
    glm::vec3(-0.5f, -0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),

    ///bottom RIGHT
    glm::vec3(0.5f, -0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
    ////TOP RIGHT
    glm::vec3(0.5f, 0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
    ///TOP LEFT
    glm::vec3(-0.5f, 0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f)

};

unsigned noOfVertices = sizeof(vertices) / sizeof(Vertex);

这是我的索引排序

GLuint indices[] =
{
    // /front face

    0, 1, 2,
    2, 3, 0,

    // right
    1, 5, 6,
    6, 2, 1,
    // back
    7, 6, 5,
    5, 4, 7,
    // left
    4, 0, 3,
    3, 7, 4,
    // bottom
    4, 5, 1,
    1, 0, 4,
    // top
    3, 2, 6,
    6, 7, 3


};

unsigned noOfIndices = sizeof(indices) / sizeof(GLuint);

主要功能和初始化窗口

  int main()
    {

启动窗口

    ///initialise GLFW for Window
    if (glfwInit() == GLFW_FALSE)
    {
        std::cout << "ERROR::GLFW-INTI::FAILED" << "\n";
        glfwTerminate();
    }

    ///Create window with functions
    GLFWwindow* window;
    const int window_height = 480;
    int window_width = 680;
    int framebuffer_height = window_height;
    int framebuffer_width = window_width;
    char* title = "mytutorial";

    int GLverMAJ = 3;
    int GLverMin = 3;

    ///sets how  the window should be drawn and which hints
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GLverMAJ);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GLverMin);
    glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);

    ///create the window with the previously set options
    window = glfwCreateWindow(window_width, window_height, title, NULL, NULL);

    //checks if window created
    if (window == nullptr)
    {
        std::cout << "ERROR:::GLFWCREATEWINDOWFAILED" << "\n";
    }

    ///sets the frame buffer size
    glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
    glfwMakeContextCurrent(window);

    //need to read on this part
    glewExperimental = GL_TRUE;

    //initiliase the glew
    if (glewInit() != GLEW_OK)
    {
        std::cout << "ERROR::GLEWINIT::FAILED" << "\n";
    }

初始化opengl选项

///enable functions first
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glEnable(GL_CULL_FACE);

        //initialise the enabled  functions
        glCullFace(GL_BACK);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glDepthFunc(GL_LESS);

        ///set the way its draw
        glFrontFace(GL_CCW);

        ///set the polygon mode and fill ////Set as GL_LINE TO LOOK AT CUBE MESH
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

这是我在其中初始化视图,项目和模型的矩阵的地方
        ///初始化矩阵

    ///view
    ///front, position, up then use in lookat
    glm::vec3 cameraPos(0.f, 0.f, 1.f);
    glm::vec3 cameraUp(0.f, 1.f, 0.f);
    glm::vec3 cameraFront(0.f, 0.f, -0.1f);

    glm::mat4 ViewMatrix(1.f);
    ViewMatrix = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);

    ///set up prespective projection

    float fov = 90.f;
    float nearPlane = -1.f;
    float farPlane = 1000.f;

    ///projection
    glm::mat4 ProjectionMatrix(1.f);
    ProjectionMatrix = glm::perspective(glm::radians(fov), static_cast<float>(framebuffer_width / framebuffer_height), nearPlane, farPlane);


    //Model Matrix
    glm::mat4 ModelMatrix(1.f);

然后我创建我的着色器

    ///set up SHADERS
    char infolog[512];
    GLint success;

    GLuint Vertexshader = glCreateShader(GL_VERTEX_SHADER);
    ///std::string str_src = 

    std::string temp = "";
    std::string src = "";
    std::ifstream infile;
    infile.open("vert.glsl");
    if (infile.is_open())
    {
        while (std::getline(infile, temp))
            src += temp + "\n";

    }
    infile.close();

    const GLchar* source = src.c_str();

    ///link created shader with shader source
    glShaderSource(Vertexshader, 1, &source, NULL);
    glCompileShader(Vertexshader);

    ///error check compilation status
    glGetShaderiv(Vertexshader, GL_COMPILE_STATUS, &success);

    if (!success)
    {
        glGetShaderInfoLog(Vertexshader, 512, NULL, infolog);
        std::cout << infolog;
    }



    success = 0;

    GLuint FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    ///std::string str_src = 

    temp = "";
    src = "";
    infile.open("frag.glsl");
    if (infile.is_open())
    {
        while (std::getline(infile, temp))
            src += temp + "\n";

    }
    infile.close();

    source = src.c_str();

    ///link created shader with shader source
    glShaderSource(FragmentShader, 1, &source, NULL);
    glCompileShader(FragmentShader);

    ///error check compilation status
    glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &success);

    if (!success)
    {
        glGetShaderInfoLog(FragmentShader, 512, NULL, infolog);
        std::cout << infolog;
    }

将创建的着色器与程序链接

     ///create and link the program
    success = 0;
    GLuint programID;

    programID = glCreateProgram();

    glAttachShader(programID, Vertexshader);
    glAttachShader(programID, FragmentShader);

    glLinkProgram(programID);

    glGetProgramiv(programID, GL_LINK_STATUS, &success);
    if (!success)
    {
        glGetProgramInfoLog(programID, 512, NULL, infolog);
        std::cout << "ERROR::SHADER::COULD_NOT_LINK_PROGRAM" << "\n";
        std::cout << infolog << "\n";

    }

链接未使用和删除的缓冲区后

///after linking we unuse the program and delete the shaders
    glUseProgram(0);
    glDeleteShader(Vertexshader);
    glDeleteShader(FragmentShader);

这是我发起VAO VBO和EBO的地方

///vbo, ebo and vertex array
    GLuint VAO;
    GLuint VBO;
    GLuint EBO;

    //gen and bind vao
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);


    ///gen vbo
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, noOfVertices * sizeof(Vertex), vertices, GL_STATIC_DRAW);


    ///gen EBO
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, noOfIndices * sizeof(GLuint), indices, GL_STATIC_DRAW);

这是我觉得可能有问题的部分

    ///tell  buffer where data is located
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, position));
    glEnableVertexAttribArray(0);

    //colour
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, color));
    glEnableVertexAttribArray(1);

    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, normal));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0);

    ///use program send in uniforms to the shader.
    glUseProgram(programID);

    ///GLuint s = glGetUniformLocation(programID, "ViewMatrix");
    GLuint s = glGetUniformLocation(programID, "ModelMatrix");
    glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ModelMatrix));

    s = glGetUniformLocation(programID, "ProjectionMatrix");
    glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ProjectionMatrix));

    s = glGetUniformLocation(programID, "ViewMatrix");
    glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ViewMatrix));

    glUseProgram(0);
    ///main while loop
    while (!glfwWindowShouldClose(window))
    {
        //clear
        glClearColor(0.f, 0.f, 0.f, 1.f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        ///draw
        glfwPollEvents();



        glUseProgram(programID);
        glBindVertexArray(VAO);


        glDrawElements(GL_TRIANGLES, noOfIndices, GL_UNSIGNED_INT, 0);

        ///flush

        glfwSwapBuffers(window);
        glFlush();


    ///unuse

        glBindVertexArray(0);
        glUseProgram(0);
    }



    return 0;
}

2 个答案:

答案 0 :(得分:0)

在我看来,您的程序似乎正常运行。如果我没记错的话,那么您的相机就位于立方体内部,从其中一个面的位置直视另一侧的面。您所看到的正是在这种情况下所期望看到的。在图像的中心,您有两个三角形,它们构成了您所要看到的脸部的背面。您得到的“怪异线”只是构成其他面的三角形的边缘。由于您的相机位于立方体内部,因此这些面必定会一直延伸到相机的后方,并且所有物体都将在近平面处被切掉,在该平面上,您可以从外部“包围”所有物体。

一切都被压缩了,因为这

static_cast<float>(framebuffer_width / framebuffer_height)

不会产生您最有可能想要的效果。您仍然在这里执行整数除法。

此外,我不确定您对近平面使用负值会产生什么样的效果。很有可能,这也不是您真正想要的,我建议您在其中使用一些正值,例如0.1f

答案 1 :(得分:0)

glm::perspective的近平面和远平面都必须为正值,static_cast<float>(framebuffer_width / framebuffer_height)将是整数除法:

float fov = 90.f;
float nearPlane = 0.1f; // 0.1 instead of -1.0
float farPlane = 1000.f;

glm::mat4 ProjectionMatrix(1.f);
ProjectionMatrix = glm::perspective(glm::radians(fov), 
    static_cast<float>(framebuffer_width) / static_cast<float>(framebuffer_height),
    nearPlane, farPlane); 

请参见glm::perspective

GLM_FUNC_DECL mat<4, 4, T, defaultp> glm::perspective(
      T     fovy,
      T     aspect,
      T     near,
      T     far 
  )
     

[...]
  near指定从查看者到附近剪切平面的距离(始终为正)。
  far指定查看者到远裁剪平面的距离(始终为正)。


glm 库提供与OpenGL和GLSL相关的矩阵运算。 glm API documentation指的是The OpenGL Shading Language specification 4.20

请参见The OpenGL Shading Language 4.6, 5.4.2 Vector and Matrix Constructors, page 101

  

要通过指定向量或标量来初始化矩阵,必须按列优先顺序将分量分配给矩阵元素。

mat4(float, float, float, float,  // first column
       float, float, float, float,  // second column
       float, float, float, float,  // third column
       float, float, float, float); // fourth column

这意味着顶点着色器中顶点坐标的转换必须为:

gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(vertex_position,1.0);

另请参阅GLSL Programming/Vector and Matrix Operations

很可能通过将glUniformMatrix4fv的第三参数设置为GL_TRUE,可以将矩阵设置为统一矩阵时进行转置:

GLuint s = glGetUniformLocation(programID, "ModelMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ModelMatrix));

s = glGetUniformLocation(programID, "ProjectionMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ProjectionMatrix));

s = glGetUniformLocation(programID, "ViewMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ViewMatrix));

并以相反顺序计算顶点坐标转换:

gl_Position = vec4(vertex_position,1.0) * ModelMatrix * ViewMatrix * ProjectionMatrix;

此外,立方体a的面的缠绕顺序为顺时针,因此必须为:

glFrontFace(GL_CCW);
glFrontFace(GL_CW);


将相机位置更改为

glm::vec3 cameraPos(0.f, 0.f, 2.f);

您将得到以下结果: