OpenGL多维数据集未呈现

时间:2015-05-29 22:38:46

标签: c++ opengl 3d

我正努力让一个立方体在opengl中渲染。当我将已计算的MVP传递给顶点着色器时,它工作正常,但是当我传入模型时,查看和投影然后在顶点着色器中进行计算,它不会显示立方体。当我将顶点着色器的统一类型更改为mat4而不是vec4时,我也得到错误1282。

Main.cpp的

#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <fstream>
#include <stdlib.h>
#include <vector>

GLuint getShader(const char* shaderName, GLenum shaderType) {
    std::cout << "Making shader " << shaderName << std::endl;

    /* Read file */
    std::cout << "Reading shader file" << std::endl;
    std::ifstream shaderFile;
    shaderFile.open(shaderName, std::ios_base::in);

    if (!shaderFile) {
        std::cout << shaderName << " not found" << std::endl;
        return 0;
    }

    std::string line;
    std::string shaderData;
    while (std::getline(shaderFile, line)) {
        shaderData += line + "\n";
    }

    shaderFile.close();

    /* Create shader */
    std::cout << "Compiling shader" << std::endl;
    GLuint shader = glCreateShader(shaderType);

    if (shader == 0) {
        std::cout << "Failed to create shader for " << shaderName << std::endl;
        return 0;
    }

    const char *shaderStr = shaderData.c_str();

    glShaderSource(shader, 1, &shaderStr, nullptr);
    glCompileShader(shader);

    /* Check compile status */
    GLint status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status != GL_TRUE) {
        GLint logLength;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);

        GLchar *infoLog = new GLchar[logLength + 1];
        glGetShaderInfoLog(shader, logLength, nullptr, infoLog);

        std::cout << shaderName << " failed to compile: " << infoLog << std::endl;
        return 0;
    }

    GLenum error = glGetError();
    if(error != GL_NO_ERROR) {
        std::cout << "Failed making shader program, error " << error << ": " << glewGetErrorString(error) << std::endl;
        return 0;
    }

    return shader;
}

int end(const char* message) {
    glfwTerminate();

    if(message != nullptr) {
        std::cout << message << std::endl;
        system("PAUSE");
    }
    return -1;
}

struct Shader {
    const char* file;
    GLenum type;

    Shader(const char* file, GLenum type) {
        this->type = type;
        this->file = file;
    }
};

GLuint getShader(Shader& shader) {
    return getShader(shader.file, shader.type);
}

GLuint getShaderProgram(std::initializer_list<Shader> shaders, std::initializer_list<const char*> binds) {
    /* Create the shader program */
    GLuint shaderProgram = glCreateProgram();
    GLenum error = glGetError();

    if (shaderProgram == 0) {
        std::cout << "Failed to create shader program" << std::endl;
        return 0;
    }
    else if (glIsProgram(shaderProgram) != GL_TRUE) {
        std::cout << "Failed to create shader program" << std::endl;
        return 0;
    }
    else if(error != GL_NO_ERROR) {
        std::cout << "Failed creating shader program, error " << error << ": " << glewGetErrorString(error) << std::endl;
        return 0;
    }

    /* Compile & attach the shaders */
    for(Shader shader : shaders) {
        GLuint glShader = getShader(shader);

        if (glShader == 0) {
            std::cout << "Failed to load shader " << shader.file << std::endl;
            return 0;
        }

        std::cout << "Attaching shader " << shader.file << std::endl;
        glAttachShader(shaderProgram, glShader);
        glDeleteShader(glShader);

        error = glGetError();
        if(error != GL_NO_ERROR) {
            std::cout << "Failed attaching shader, error " << error << ": " << glewGetErrorString(error) << std::endl;
            return 0;
        }
    }

    /* Bind */
    for(const char* bind : binds) {
        std::cout << "Binding data location " << bind << std::endl;
        glBindFragDataLocation(shaderProgram, 0, bind);

        error = glGetError();
        if(error != GL_NO_ERROR) {
            std::cout << "Failed binding data location, error " << error << ": " << glewGetErrorString(error) << std::endl;
            return 0;
        }
    }

    /* Link to opengl */
    glLinkProgram(shaderProgram);
    error = glGetError();
    if(error != GL_NO_ERROR) {
        std::cout << "Failed linking shader program, error " << error << ": " << glewGetErrorString(error) << std::endl;
        return 0;
    }

    return shaderProgram;
}

int main() {
    /* Initial checks */
    if (!glfwInit()) {
        return end("Failed to startup GLFW");
    }

    int major = 3;
    int minor = 3;
    int rev = 0;
    glfwGetVersion(&major, &minor, &rev);

    /* Create the window */
    GLFWwindow *window = glfwCreateWindow(500, 500, "3D world prototyping", nullptr, nullptr);

    if (!window) {
        return end("Failed to create window.");
    }

    glfwMakeContextCurrent(window); //make the window active

    /* Startup GLEW */
    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK) {
        return end("Failed to startup GLEW");
    }

    /* Start OpenGL constants */
    glEnable(GL_DEPTH_TEST);
    glEnableClientState(GL_VERTEX_ARRAY);
    glViewport(0, 0, 800, 600);

    /* Support for multiple shaders without the need to switch attributes */
    GLuint vertexArray;
    glGenVertexArrays(1, &vertexArray);
    glBindVertexArray(vertexArray);

    /* Shape vectors */
    GLfloat verticies[] = {//X, Y, Z
            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,

            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,

            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,

            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f
    };

    GLuint shaderProgram = getShaderProgram({
        Shader("vertexShader.glsl", GL_VERTEX_SHADER),
        Shader("fragmentShader.glsl", GL_FRAGMENT_SHADER)
    }, {
        "outcolor"
    });

    if(shaderProgram == 0) {
        return end("");
    }

        /* Load verticies into memory */
    GLuint vertexBuffer;
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticies), verticies, GL_STATIC_DRAW);

    /* Getting uniform ids */
    glUseProgram(shaderProgram);
//    GLint mvpId = glGetUniformLocation(shaderProgram, "mvp");
    GLint projectionId = glGetUniformLocation(shaderProgram, "projection");
    GLint modelId = glGetUniformLocation(shaderProgram, "model");
    GLint viewId = glGetUniformLocation(shaderProgram, "view");

    GLenum error = glGetError();
    if(error != GL_NO_ERROR) {
        std::cout << "Uniform error " << error << ": " << glewGetErrorString(error) << std::endl;
        return end("");
    }
//    else if(mvpId == -1) {
//        return end("MVP ID failed to load");
//    }

    GLint positionAttribute = glGetAttribLocation(shaderProgram, "position");

    if(positionAttribute == -1) {
        std::cout << "Error: position attribute failed to load" << std::endl;
        return end("");
    }

    /* Positioning */
    //FOV, Screen ratio, display range short, display range long
    glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 1.0f, 10.0f);
    glm::mat4 model = glm::mat4(1.0f);
    glm::mat4 mvp;

    glm::vec3 camera = glm::vec3(0.0f, 0.0f, 3.0f);
    glm::vec3 cameraLookingAt = glm::vec3(0.0f, 0.0f, 0.0f);
    glm::vec3 cameraPitch = glm::vec3(0.0f, 1.0f, 0.0f);
    float moveSpeed = 0.1f;

    /* Rendering and logic */
    while (!glfwWindowShouldClose(window)) {
        /* Shutdown logic */
        if (glfwGetKey(window, GLFW_KEY_ESCAPE)) {
            break;
        }

        /* Clear */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);

        /* Logic */
            /* Keypresses */
        glfwPollEvents();
        if(glfwGetKey(window, GLFW_KEY_W)) {
            camera.z -= moveSpeed;
            cameraLookingAt.z -= moveSpeed;
        }
        else if(glfwGetKey(window, GLFW_KEY_S)) {
            camera.z += moveSpeed;
            cameraLookingAt.z += moveSpeed;
        }

        if(glfwGetKey(window, GLFW_KEY_A)) {
            camera.x -= moveSpeed;
            cameraLookingAt.x -= moveSpeed;
        }
        else if(glfwGetKey(window, GLFW_KEY_D)) {
            camera.x += moveSpeed;
            cameraLookingAt.x += moveSpeed;
        }

        if(glfwGetKey(window, GLFW_KEY_Z)) {
            camera.y += moveSpeed;
            cameraLookingAt.y += moveSpeed;
        }
        else if(glfwGetKey(window, GLFW_KEY_X)) {
            camera.y -= moveSpeed;
            cameraLookingAt.y -= moveSpeed;
        }

        if(glfwGetKey(window, GLFW_KEY_UP)) {
            cameraLookingAt.y += moveSpeed;
        }
        else if(glfwGetKey(window, GLFW_KEY_DOWN)) {
            cameraLookingAt.y -= moveSpeed;
        }

        if(glfwGetKey(window, GLFW_KEY_LEFT)) {
            cameraLookingAt.x -= moveSpeed;
            cameraLookingAt.z -= moveSpeed;
        }
        else if(glfwGetKey(window, GLFW_KEY_RIGHT)) {
            cameraLookingAt.x += moveSpeed;
            cameraLookingAt.z += moveSpeed;
        }

            /* Update position */
        mvp = projection * glm::lookAt(
                camera,
                cameraLookingAt,
                cameraPitch
        ) * model;
        glm::mat4 view = glm::lookAt(
                camera,
                cameraLookingAt,
                cameraPitch
        );

        /* Draw */
        glUseProgram(shaderProgram);

            /* Update the position */
//        glUniformMatrix4fv(mvpId, 1, GL_FALSE, &mvp[0][0]);
        glUniform4fv(viewId, 1, glm::value_ptr(view));
        glUniform4fv(modelId, 1, glm::value_ptr(model));
        glUniform4fv(projectionId, 1, glm::value_ptr(projection));

            /* Redraw the position using the verticies */
        glEnableVertexAttribArray(positionAttribute);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glVertexAttribPointer(positionAttribute, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); //because not just XYZ need to tell opengl the size of the stride

            /* Draw the triangles */
        glDrawArrays(GL_TRIANGLES, 0, 36);
        glDisableVertexAttribArray(positionAttribute);
        glfwSwapBuffers(window);

        /* Realtime error checking */
        error = glGetError();
        if(error != GL_NO_ERROR) {
            std::cout << "Error " << error << ": " << glewGetErrorString(error) << std::endl;
        }
    }

    glfwDestroyWindow(window);
    glDeleteProgram(shaderProgram);
    glDeleteBuffers(1, &vertexBuffer);
    glDeleteVertexArrays(1, &vertexArray);
    return end(nullptr);
}

顶点着色器:

#version 330

uniform mat4 projection; /* view port / perspective */
uniform mat4 model; /* object */
uniform mat4 view; /* camera */
in vec3 position;

void main() {
    gl_Position = projection * view * model * vec4(position, 1.0);
}

2 个答案:

答案 0 :(得分:2)

您需要在调用glVertexAttribPointer时指定一个步幅,因为您的顶点未打包(您有位置和颜色数据交错):

glVertexAttribPointer(positionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0);

答案 1 :(得分:1)

我修好了!

我要做的第一件事就是添加我的缓冲区绑定和属性指向while循环,我猜你每次调用useProgram时都要告诉opengl。

第二件事是我需要调用glUniformMatrix4fv,如果我想将我的值传递给mat4(他们需要的是,而不是vec4)。