簡體   English   中英

停留在基本的OpenGL程序上

[英]Stuck on a basic OpenGL program

我正在嘗試創建一個示例程序,可用作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返回一個整數,該整數表示程序對象中特定統一變量的位置。 名稱必須是不包含空格的以空終止的字符串。 名稱必須是程序 的活性均勻的變量名 不是一個結構,結構的陣列,或載體或基質的子組件

glGetUniform參數 glGetUniform返回指定統一變量的值。 location指定的統一變量的類型決定了返回值的數量。 如果在着色器中將統一變量定義為布爾值,整數或浮點型,則將返回單個值。 如果將其定義為vec2,ivec2或bvec2,則將返回兩個值。 如果將其定義為vec3,ivec3或bvec3,則將返回三個值,依此類推。 要查詢存儲在聲明為數組的統一變量中的值,請為數組的每個元素調用glGetUniform 要查詢存儲在聲明為結構的統一變量中的值,請為結構中的每個字段調用glGetUniform 聲明為矩陣的統一變量的值將按列主順序返回。

您的統一變量uniform mat4 MVPMatrix; 聲明為矩陣類型 ,而不是數組 ,您將立即檢索整個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個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM