c++ - 停留在一个基本的 OpenGL 程序上

标签 c++ opengl

我正在尝试创建一个可用作 OpenGL 测试工具的示例程序。到目前为止,我的那个似乎可以工作,但似乎忽略了通过统一变量 MVPMatrix 传递的 MVP 矩阵。当我添加代码以读回制服并检查它是否确实正确更新时,我在这样做时收到无效操作错误,我不明白为什么 - 发生了什么?

#include "stdafx.h"
#include <iostream>
#include <memory>
#include <sdl/SDL.h>
#include <assimp/Importer.hpp>
#include <assimp/mesh.h>
#include <assimp/scene.h>
#include <sdl/SDL_image.h>
#include <glm/glm.hpp>
#include <Windows.h>
#include <GL/glew.h>
#include <GL/GL.h>
#include <gl/GLU.h>
#include <vector>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <assimp/Importer.hpp>
#include <assimp/mesh.h>
#include <assimp/postprocess.h>
#include <assimp/vector3.h>

using namespace std;


void checkGLShaderStatus(GLuint id, GLuint thingToCheck, bool shader) {
    GLint ret;
    if (shader) glGetShaderiv(id, thingToCheck, &ret); else glGetProgramiv(id, thingToCheck, &ret);

    // If there was an error
    if (ret == GL_FALSE) {
        // Print it out, then halt
        GLint maxLength = 0;
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &maxLength);
        GLchar *shaderErrorLog = (GLchar*)malloc(sizeof(GLchar)*(maxLength + 1));
        glGetShaderInfoLog(id, maxLength, &maxLength, shaderErrorLog);
        shaderErrorLog[maxLength] = '\0';
        cout << shaderErrorLog;
        free(shaderErrorLog);
        int junk;
        cin >> junk;

        exit(EXIT_FAILURE);
    }
}

GLuint buildShader(const GLchar **source, GLuint length, GLenum type) {
    // Create the shader
    GLuint shaderId = glCreateShader(type);
    // Upload source code
    glShaderSource(shaderId, length, source, NULL);
    // Compile the shader
    glCompileShader(shaderId);
    // See how the compilation went
    checkGLShaderStatus(shaderId, GL_COMPILE_STATUS, true);
    return shaderId;
}

void checkGL(string stage) {
    GLuint error = glGetError();
    if (error != GL_NO_ERROR) {
        cout << "OpenGL broke..";
        switch (error) {
        case GL_INVALID_ENUM:
            cout << "Invalid Enum";
            break;
        case GL_INVALID_VALUE:
            cout << "Value out of range";
            break;
        case GL_INVALID_OPERATION:
            cout << "Invalid operation";
            break;
        case GL_INVALID_FRAMEBUFFER_OPERATION:
            cout << "Incomplete framebuffer";
            break;
        case GL_OUT_OF_MEMORY:
            cout << "Out of memory";
            break;
        default:
            cout << "Oh boy, did it break..";
        }
        cout << " (" << stage << ")" << endl;
        int junk;
        cin >> junk;
        exit(EXIT_FAILURE);
    }

}
int _tmain(int argc, _TCHAR* argv[])
{
    if (SDL_Init(SDL_INIT_EVERYTHING) == -1) exit(EXIT_FAILURE);
    if (IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG) == -1) exit(EXIT_FAILURE);

    Assimp::Importer importer;
    const aiScene *importedScene = importer.ReadFile("Table.3ds",aiProcess_Triangulate);
    if (importedScene == nullptr) exit(EXIT_FAILURE);

    aiMesh *theMesh = importedScene->mMeshes[0];
    if (theMesh == nullptr) exit(EXIT_FAILURE);
    cout << "I imported a mesh with " << theMesh->mNumVertices << " vertices and " << theMesh->mNumFaces << " faces! " << endl;

    SDL_Window *win = nullptr;
    win = SDL_CreateWindow("My even more awesome SDL/OGL program", 100, 100, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
    if (win == nullptr) exit(EXIT_FAILURE);

    SDL_Renderer *ren = nullptr;
    ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (ren == nullptr) exit(EXIT_FAILURE);

    SDL_GLContext context = SDL_GL_CreateContext(win);
    if (context == nullptr) exit(EXIT_FAILURE);
    glewInit();

    int attrib_vPosition = 0;
    const GLchar *vertexShaderSource = { "#version 430 core\n"
        "layout (location=0) in vec4 vPosition;"
        "uniform mat4 MVPMatrix;"
        "void main() {"
        "  gl_Position = MVPMatrix * vPosition;"
        "}"};
    GLuint vertexShader = buildShader(&vertexShaderSource, 1, GL_VERTEX_SHADER);
    checkGL("compiling vertex shader");

    const GLchar *fragShaderSource = { "#version 430 core\n"
        "out vec4 fColor;"
        "void main() {"
        "  fColor = vec4(0.0, 0.0, 1.0, 1.0);"
        "}"
    };
    GLuint fragmentShader = buildShader(&fragShaderSource, 1, GL_FRAGMENT_SHADER);
    checkGL("compiling fragment shader");

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    checkGLShaderStatus(shaderProgram, GL_LINK_STATUS, false);
    checkGL("Linking shader");

    glUseProgram(shaderProgram);
    //glDeleteShader(fragmentShader);
    //glDeleteShader(vertexShader);
    checkGL("Running shader");

    GLint MVPlocation = glGetUniformLocation(shaderProgram, "MVPMatrix");
    checkGL("Getting uniform location");
    glm::mat4 mvpMatrix(0.1f);
    glUniformMatrix4fv(MVPlocation, 1, GL_FALSE, glm::value_ptr(mvpMatrix));
    checkGL("Setting uniform");

    GLint testLocation = glGetUniformLocation(shaderProgram, "MVPMatrix[0][0]");
    checkGL("Getting uninform test cell location");
    GLfloat testfloat;
    glGetUniformfv(shaderProgram, testLocation, &testfloat);
    checkGL("Reading uniform");
    if (testfloat != mvpMatrix[0][0]) {
        cout << "Uniform setting did not sink in..";
    }

    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);
    checkGL("Creating VAO");

    GLfloat vertices[3][3] = { { -0.9f, -0.9f, 0.f }, { 0.85f, -0.9f, 0.f }, { -0.9f, 0.85f, 0.f } };
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    int vertexDataSize = 9;
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ((void *)(0)));
    glEnableVertexAttribArray(0);
    checkGL("creating VBO");

    glClearColor(0.f, 0.f, 0.f, 1.f);
    glClear(GL_COLOR_BUFFER_BIT);
    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, vertexDataSize);
    glFlush();
    SDL_GL_SwapWindow(win);

    SDL_Event event;
    bool quit = false;

    while (!quit) {
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                quit = true;
            }
        }
    }

    glDeleteProgram(shaderProgram);
    glDeleteBuffers(1, &buffer);
    glDeleteVertexArrays(1, &VAO);
    SDL_GL_DeleteContext(context);
    SDL_DestroyRenderer(ren);
    SDL_DestroyWindow(win);
    IMG_Quit();
    SDL_Quit();
    return 0;
}

最佳答案

你不应该使用 glGetUniformfv(... glGetUniformLocation(... "MVPMatrix[0][0]"))。文档说

glGetUniformLocation returns an integer that represents the location of a specific uniform variable within a program object. name must be a null terminated string that contains no white space. name must be an active uniform variable name in program that is not a structure, an array of structures, or a subcomponent of a vector or a matrix.

glGetUniform returns in params the value(s) of the specified uniform variable. The type of the uniform variable specified by location determines the number of values returned. If the uniform variable is defined in the shader as a boolean, int, or float, a single value will be returned. If it is defined as a vec2, ivec2, or bvec2, two values will be returned. If it is defined as a vec3, ivec3, or bvec3, three values will be returned, and so on. To query values stored in uniform variables declared as arrays, call glGetUniform for each element of the array. To query values stored in uniform variables declared as structures, call glGetUniform for each field in the structure. The values for uniform variables declared as a matrix will be returned in column major order.

您的统一变量 uniform mat4 MVPMatrix; 声明为 a matrix type , 不是 an array您将立即检索整个 4x4 矩阵(就像您在一次操作中设置它一样)。尝试

GLfloat testfloat[16];
glGetUniformfv(shaderProgram, MVPLocation, testfloat);

另一个问题是:

GLfloat vertices[3][3] = { { -0.9f, -0.9f, 0.f }, { 0.85f, -0.9f, 0.f }, { -0.9f, 0.85f, 0.f } };
int vertexDataSize = 9;
glDrawArrays(GL_TRIANGLES, 0, vertexDataSize);

你没有 9 个顶点,只有 3 个。

关于c++ - 停留在一个基本的 OpenGL 程序上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22391589/

相关文章:

c++ - 为什么这个乘法会出现整数溢出?

c++ - 寻找 Java Graphics 替代品

c++ - 使用 Visual Studio 在 Opengl 1 中创建纹理动画的最佳方法是什么?

opengl - 有些面是透明的,有些是不透明的

xcode - MacOS Mojave Xcode 10 + OpenGL 在初始化窗口后未绘制

c++ - 递归的概念

flex 中的 C++ 多行注释语法

c++ - 使用 RegEnumValue 显示值名称和数据

c++ - 在 CPU 上模拟 OpenGL 纹理映射以进行重投影

opengl - 二次幂纹理的效率有多高?