带有 GLFW 和 GLEW 的 OpenGL 不渲染立方体? C++、GLM

OpenGL with GLFW and GLEW not rendering cube? C++, GLM

我对 OpenGL、GLFW 或 GLEW 的经验不多,因此我对这些库的故障排除能力很弱 none。我设法渲染了一个三角形 ([-1, -1, 0], [1, -1, 0], [0, 1, 0]) 但是当使用立方体的顶点属性坐标以及颜色属性时它似乎没有渲染。我的代码、着色器和矩阵运算可能有很多错误。我希望我能更清楚地了解我在做什么,这样我就可以对我的错误进行更具描述性的描述。目前上面的代码只渲染了 window。我最初遵循 https://learnopengl.com/ 并获得了第一个教程,下面的代码是我的“测试”文件,我试图自己重新实现一些元素。如果有帮助,可以与该教程共享很多复制粘贴的部分。

如有任何见解或建议,我们将不胜感激。

Main Source

#include "global.hpp"

using namespace std;
using namespace glm;

static const GLfloat g_color_buffer_data[] = {
    0.583f,  0.771f,  0.014f,
    0.609f,  0.115f,  0.436f,
    0.327f,  0.483f,  0.844f,
    0.822f,  0.569f,  0.201f,
    0.435f,  0.602f,  0.223f,
    0.310f,  0.747f,  0.185f,
    0.597f,  0.770f,  0.761f,
    0.559f,  0.436f,  0.730f,
    0.359f,  0.583f,  0.152f,
    0.483f,  0.596f,  0.789f,
    0.559f,  0.861f,  0.639f,
    0.195f,  0.548f,  0.859f,
    0.014f,  0.184f,  0.576f,
    0.771f,  0.328f,  0.970f,
    0.406f,  0.615f,  0.116f,
    0.676f,  0.977f,  0.133f,
    0.971f,  0.572f,  0.833f,
    0.140f,  0.616f,  0.489f,
    0.997f,  0.513f,  0.064f,
    0.945f,  0.719f,  0.592f,
    0.543f,  0.021f,  0.978f,
    0.279f,  0.317f,  0.505f,
    0.167f,  0.620f,  0.077f,
    0.347f,  0.857f,  0.137f,
    0.055f,  0.953f,  0.042f,
    0.714f,  0.505f,  0.345f,
    0.783f,  0.290f,  0.734f,
    0.722f,  0.645f,  0.174f,
    0.302f,  0.455f,  0.848f,
    0.225f,  0.587f,  0.040f,
    0.517f,  0.713f,  0.338f,
    0.053f,  0.959f,  0.120f,
    0.393f,  0.621f,  0.362f,
    0.673f,  0.211f,  0.457f,
    0.820f,  0.883f,  0.371f,
    0.982f,  0.099f,  0.879f
};
static const GLfloat g_vertex_buffer_data[] = {
    -1.0f,-1.0f,-1.0f, // triangle 1 : begin
    -1.0f,-1.0f, 1.0f,
    -1.0f, 1.0f, 1.0f, // triangle 1 : end
    1.0f, 1.0f,-1.0f, // triangle 2 : begin
    -1.0f,-1.0f,-1.0f,
    -1.0f, 1.0f,-1.0f, // triangle 2 : end
    1.0f,-1.0f, 1.0f,
    -1.0f,-1.0f,-1.0f,
    1.0f,-1.0f,-1.0f,
    1.0f, 1.0f,-1.0f,
    1.0f,-1.0f,-1.0f,
    -1.0f,-1.0f,-1.0f,
    -1.0f,-1.0f,-1.0f,
    -1.0f, 1.0f, 1.0f,
    -1.0f, 1.0f,-1.0f,
    1.0f,-1.0f, 1.0f,
    -1.0f,-1.0f, 1.0f,
    -1.0f,-1.0f,-1.0f,
    -1.0f, 1.0f, 1.0f,
    -1.0f,-1.0f, 1.0f,
    1.0f,-1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f,-1.0f,-1.0f,
    1.0f, 1.0f,-1.0f,
    1.0f,-1.0f,-1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f,-1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f, 1.0f,-1.0f,
    -1.0f, 1.0f,-1.0f,
    1.0f, 1.0f, 1.0f,
    -1.0f, 1.0f,-1.0f,
    -1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    -1.0f, 1.0f, 1.0f,
    1.0f,-1.0f, 1.0f
};

extern const char* VertexShader = R"(
#version 330 core

layout(location = 0) in vec3 vertexPosition_modelspace;

layout(location = 1) in vec3 vertexColor;

uniform mat4 MVP;
  
out vec3 fragmentColor;
 
//out vec2 UV;
  
void main(){
  gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
  
  //UV = vertexUV;
  
  fragmentColor = vertexColor;
}
)";

extern const char* FragmentShader = R"(
#version 330 core
in vec3 fragmentColor;
out vec3 color;
void main(){
  //color = vec3(1,0,0);
  color = fragmentColor;
}
)";

static const float tri_vertex_array[] = {
    -.8, .8, 0,
    -.8, -.8, 0,
    .8, -.8, 0
};

int main()
{
    if (!glfwInitFull()) {
        printf("Unable To Init\n");
        return 1;
    }

    uint width = 1200, height = 720;
    GLFWwindow* window = glfwCreateWindow(width, height, "ME", 0, 0);

    if (!window)
        return -1;

    glfwMakeContextCurrent(window);
    if (glewInit() != GLEW_OK)
        return 0;

    //
    GLuint VertexArrayId;
    glGenVertexArrays(1, &VertexArrayId);
    glBindVertexArray(VertexArrayId);
    //

    GLuint vertexBuffer;
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

    //glBufferData(GL_ARRAY_BUFFER, sizeof(tri_vertex_array), tri_vertex_array, GL_STATIC_DRAW);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);


    GLuint colorBuffer;
    glGenBuffers(1, &colorBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);


    GLuint vertexShaderId = compileShader(VertexShader, GL_VERTEX_SHADER);
    GLuint fragmentShaderId = compileShader(FragmentShader, GL_FRAGMENT_SHADER);

    GLuint programId = glCreateProgram();

    linkShader(programId, vertexShaderId);
    linkShader(programId, fragmentShaderId);

    // maybe nessacary?
    //glMatrixMode(GL_PROJECTION);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LESS);
    glEnable(GL_CULL_FACE);
    glViewport(0, 0, width, height);

    //vec3 cameraPos = vec3(0.f, 0.f, 3.f);
    //vec3 cameraTarget = vec3(0.f, 0.f, 0.f);
    //vec3 cameraDirection = normalize(cameraPos - cameraTarget);
    //
    //vec3 up = vec3(0.f, 1.f, 0.f);
    //vec3 right = normalize(
    //    cross(
    //        up,
    //        cameraDirection
    //    )
    //);
    //
    //vec3 cameraUp = cross(cameraDirection, right);
    //
    //mat4 view = lookAt(
    //    vec3(4.f, 3.f, 3.f),
    //    vec3(0.f, 0.f, 0.f),
    //    vec3(0.f, 1.f, 0.f)
    //);

    mat4 projection = perspective(radians(45.f), width / (float)height, .1f, 100.f);
    mat4 view = lookAt(
        vec3(4, 3, -3),
        vec3(0, 0, 0),
        vec3(0, 1, 0)
    );

    mat4 model = mat4(1.0f); // identity
    mat4 mvp = projection * view * model;

    GLuint mvpId = glGetUniformLocation(programId, "MVP");

    do {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClearColor(0.f, 0.f, .4f, 0.f);

        glUseProgram(programId);

        //gluLookAt(
        //    4, 3, 3,
        //    0, 0, 0,
        //    0, 1, 0
        //);

        glUniformMatrix4fv(mvpId, 1, 0, &mvp[0][0]);

        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glVertexAttribPointer(
            0,
            3,
            GL_FLOAT,
            GL_FALSE,
            0,
            NULL
        );

        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
        glVertexAttribPointer(
            1,          
            3,          
            GL_FLOAT,   
            GL_FALSE,   
            0,          
            (void*)0    
        );

        glDrawArrays(GL_TRIANGLES, 0, 3*12);

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);

        glfwSwapBuffers(window);
        glfwPollEvents();
    } while (
        !glfwWindowShouldClose(window)
        &&
        !glfwGetKey(window, GLFW_KEY_ESCAPE)
    );

    glfwTerminate();
}

global.hpp

#ifndef _glfw3_h_
// opengl extensions
#include <GL/glew.h>

// opengl utility / wrapper
#include <GLFW/glfw3.h>

// operations in space
#include <glm/glm.hpp>

#include <glm/gtc/matrix_transform.hpp>

#endif // !_glfw3_h_


#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include <fstream>

#include <random>
#include <ctime>
#include <cmath>

static void glfwErrorCb(int errorCode, const char* error) {
    printf("GLFW Error Thrown\n -> %d\n%s\n", errorCode, error);
}

static bool glfwInitFull() {
    srand(time(0));

    if (!glfwInit())
        return 0;

    glfwSetErrorCallback(glfwErrorCb);
    glewExperimental = true;

    glfwWindowHint(GLFW_SAMPLES, 4); // anti-aliasing
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // version
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // version
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // no-old-gl

    return 1;
}

static GLuint compileShader(const char* content, GLenum type) {
    GLuint shaderId = glCreateShader(type);
    GLint returnValBuf;

    glShaderSource(shaderId, 1, &content, NULL);
    glCompileShader(shaderId);

    glGetShaderiv(shaderId, GL_COMPILE_STATUS, &returnValBuf);

    if (returnValBuf == GL_FALSE) {
        printf("Unable To Compile Shader\n```\n%s\n```\n\nInfo Log:\n", content);
        
        GLint logLen;
        glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLen);

        if (logLen <= 0)
            return 0;

        char* infoBuffer = new char[logLen + 1];
        infoBuffer[logLen] = '[=11=]';
            
        glGetShaderInfoLog(shaderId, logLen, &returnValBuf, infoBuffer);
        printf("%s\n", infoBuffer);

        delete[] infoBuffer;
        return 0;
    }
    
    return shaderId;
}

static GLuint linkShader(GLuint programId, GLuint shaderId) {
    glAttachShader(programId, shaderId);
    glLinkProgram(programId);

    GLint returnValBuf;
    glGetProgramiv(programId, GL_LINK_STATUS, &returnValBuf);
    
    if (returnValBuf == GLFW_FALSE) {
        printf("Unable To Link Shader\nInfo Log:\n");

        GLint logLen;
        glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);

        if (logLen <= 0)
            return 0;

        char* infoBuffer = new char[logLen + 1];
        infoBuffer[logLen] = '[=11=]';

        glGetProgramInfoLog(programId, logLen, &returnValBuf, infoBuffer);
        printf("%s\n", infoBuffer);

        delete[] infoBuffer;
    }

    glDetachShader(programId, shaderId);
    glDeleteShader(shaderId);

    return programId;
}

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ullong;

#pragma once

问题是您为每个着色器单独调用 linkShader。可以多次 link 一个程序。然而,函数 linkShader 将着色器附加到程序, link es 程序并将着色器与程序分离。因此,顶点和片段着色器永远不会同时附加。

附加顶点和片段着色器并调用linkShader一次:

static GLuint linkShader(GLuint programId) {
    glLinkProgram(programId);

    GLint returnValBuf;
    glGetProgramiv(programId, GL_LINK_STATUS, &returnValBuf);

    if (returnValBuf == GLFW_FALSE) {
        printf("Unable To Link Shader\nInfo Log:\n");

        GLint logLen;
        glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);

        if (logLen <= 0)
            return 0;

        char* infoBuffer = new char[logLen + 1];
        infoBuffer[logLen] = '[=10=]';

        glGetProgramInfoLog(programId, logLen, &returnValBuf, infoBuffer);
        printf("%s\n", infoBuffer);

        delete[] infoBuffer;
    }

    return programId;
}
int main()
{
    // [...]

    GLuint vertexShaderId = compileShader(VertexShader, GL_VERTEX_SHADER);
    GLuint fragmentShaderId = compileShader(FragmentShader, GL_FRAGMENT_SHADER);

    GLuint programId = glCreateProgram();
    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, fragmentShaderId);

    linkShader(programId);
    
    glDetachShader(programId, vertexShaderId);
    glDeleteShader(vertexShaderId);
    glDetachShader(programId, fragmentShaderId);
    glDeleteShader(fragmentShaderId);

    // [...]
}