坚持一个基本的OpenGL程序

时间:2014-03-13 21:43:13

标签: 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;
}

1 个答案:

答案 0 :(得分:1)

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

  

glGetUniformLocation返回一个整数,表示程序对象中特定统一变量的位置。 name必须是不包含空格的空终止字符串。 名称必须是程序 中的活动统一变量名称,它不是结构,结构数组或向量或矩阵的子组件

  

glGetUniform params 中返回指定统一变量的值。 location 指定的统一变量的类型决定了返回的值的数量。如果统一变量在着色器中定义为boolean,int或float,则将返回单个值。如果将其定义为vec2,ivec2或bvec2,则将返回两个值。如果将其定义为vec3,ivec3或bvec3,则将返回三个值,依此类推。要查询存储在声明为数组的统一变量中的值,请为数组的每个元素调用glGetUniform。要查询存储在声明为结构的统一变量中的值,请为结构中的每个字段调用glGetUniform声明为矩阵的统一变量的值将按列主要顺序返回。

您的统一变量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个顶点。