GLSL统一mat4始终为0

时间:2019-02-10 20:03:55

标签: c++ qt opengl glsl

我试图将正投影投影矩阵加载到着色器中,但是当我运行代码并在窗口中单击时,最终所有点都指向(0,0,0), m的猜测是由于从未设置统一矩阵而导致的,因此所有内容都被乘以0。为此,我使用了Qt,OpenGL和GLM。任何想法为什么会这样?

我已经对其进行了一些调试,在将矩阵加载到resizeGL和initializeGL中的着色器中时似乎出现了问题,虽然不确定原因。

谢谢!

我的类处理所有OpenGL内容:

GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent), outline(false), drawMode(0) {
    num_pts = 0;
    drawMode = GL_POINTS;
    next = 1;

    ortho = glm::ortho(0.0f, 640.0f, 480.0f, 0.0f);

}

GLWidget::~GLWidget() {
}

void GLWidget::keyPressEvent(QKeyEvent *event) {
    switch (event->key()) {
    case Qt::Key_C:
        cout << "Cleared all the points." << endl;
        num_pts = 0;

        pts.clear();

        glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
        glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);
        break;
    case Qt::Key_W:
        outline = !outline;
        if (outline) {
            cout << "Displaying outlines." << endl;
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        }
        else {
            cout << "Displaying filled polygons." << endl;
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        }
        break;
    case Qt::Key_Space:
        switch (next) {
        case(0):
            drawMode = GL_POINTS;

            cout << "drawMode is GL_POINTS" << endl;

            next = 1;
            break;
        case(1):
            drawMode = GL_LINES;

            cout << "drawMode is GL_LINES" << endl;

            next = 2;
            break;
        case(2):
            drawMode = GL_LINE_STRIP;

            cout << "drawMode is GL_LINE_STRIP" << endl;

            next = 3;
            break;
        case(3):
            drawMode = GL_LINE_LOOP;

            cout << "drawMode is GL_LINE_LOOP" << endl;

            next = 4;
            break;
        case(4):
            drawMode = GL_TRIANGLES;

            cout << "drawMode is GL_TRIANGLES" << endl;

            next = 5;
            break;
        case(5):
            drawMode = GL_TRIANGLE_STRIP;

            cout << "drawMode is GL_TRIANGLE_STRIP" << endl;

            next = 6;
            break;
        case(6):
            drawMode = GL_TRIANGLE_FAN;

            cout << "drawMode is GL_TRIANGLE_FAN" << endl;

            next = 0;
            break;
        }
        break;
    case Qt::Key_P:

        cout << "Projection Location: " << projectionMatrixLoc << endl << endl;

        cout << "Projection Matrix:" << endl << endl;
        cout << "------------" << endl;
        cout << ortho[0][0] << " ";
        cout << ortho[1][0] << " ";
        cout << ortho[2][0] << " ";
        cout << ortho[3][0] << endl;
        cout << "------------" << endl;
        cout << ortho[0][1] << " ";
        cout << ortho[1][1] << " ";
        cout << ortho[2][1] << " ";
        cout << ortho[3][1] << endl;
        cout << "------------" << endl;
        cout << ortho[0][2] << " ";
        cout << ortho[1][2] << " ";
        cout << ortho[2][2] << " ";
        cout << ortho[3][2] << endl;
        cout << "------------" << endl;
        cout << ortho[0][3] << " ";
        cout << ortho[1][3] << " ";
        cout << ortho[2][3] << " ";
        cout << ortho[3][3] << endl;
        cout << "------------" << endl << endl << endl;

        break;
    }
    update();
}

void GLWidget::mousePressEvent(QMouseEvent *event) {

    glm::vec2 temp = glm::vec2(0.0);
    temp.x = event->x();
    temp.y = event->y();


    pts.push_back(temp);

    cout << "Added point (" << pts.back().x << ", " << pts.back().y << ") " << endl;
    cout << "Number of points: " << pts.size() << endl;
    num_pts++;

    glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
    glBufferData(GL_ARRAY_BUFFER, pts.size(), &pts, GL_DYNAMIC_DRAW);
    update();
}

void GLWidget::initializeGL() {
    initializeOpenGLFunctions();

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glPointSize(4.0f);

    // Create a new Vertex Array Object on the GPU which
    // saves the attribute layout of our vertices.
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    // Create a buffer on the GPU for position data
    glGenBuffers(1, &positionBuffer);

    // Upload the position data to the GPU, storing
    // it in the buffer we just allocated.
    glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
    glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);

    // Load our vertex and fragment shaders into a program object
    // on the GPU
    program = loadShaders(":/vert.glsl", ":/frag.glsl");

    // Bind the attribute "position" (defined in our vertex shader)
    // to the currently bound buffer object, which contains our
    // position data for a single triangle. This information 
    // is stored in our vertex array object.
    glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
    GLint positionIndex = glGetAttribLocation(program, "position");
    glEnableVertexAttribArray(positionIndex);
    glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glUseProgram(program);
    projectionMatrixLoc = glGetUniformLocation(program, "ProjectionMatrix");

    glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, glm::value_ptr(ortho));
}

void GLWidget::resizeGL(int w, int h) {
    glViewport(0, 0, w, h);

    ortho = glm::ortho(0.0f, (float)w, (float)h, 0.0f);

    glUseProgram(program);
// problem area?
    glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, glm::value_ptr(ortho));
}

void GLWidget::paintGL() {
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(program);

    // draw primitives based on the current draw mode
    glDrawArrays(drawMode, 0, num_pts);

    // draw points so we can always see them
    // glPointSize adjusts the size of point
    // primitives
    glDrawArrays(GL_POINTS, 0, num_pts);
}

// Copied from LoadShaders.cpp in the the oglpg-8th-edition.zip
// file provided by the OpenGL Programming Guide, 8th edition.
const GLchar* GLWidget::readShader(const char* filename) {
#ifdef WIN32
    FILE* infile;
    fopen_s(&infile, filename, "rb");
#else
    FILE* infile = fopen(filename, "rb");
#endif // WIN32

    if (!infile) {
#ifdef _DEBUG
        std::cerr << "Unable to open file '" << filename << "'" << std::endl;
#endif /* DEBUG */
        return NULL;
    }

    fseek(infile, 0, SEEK_END);
    int len = ftell(infile);
    fseek(infile, 0, SEEK_SET);

    GLchar* source = new GLchar[len + 1];

    fread(source, 1, len, infile);
    fclose(infile);

    source[len] = 0;

    return const_cast<const GLchar*>(source);
}

GLuint GLWidget::loadShaders(const char* vertf, const char* fragf) {
    GLuint program = glCreateProgram();

    // read vertex shader from Qt resource file
    QFile vertFile(vertf);
    vertFile.open(QFile::ReadOnly | QFile::Text);
    QString vertString;
    QTextStream vertStream(&vertFile);
    vertString.append(vertStream.readAll());
    std::string vertSTLString = vertString.toStdString();

    const GLchar* vertSource = vertSTLString.c_str();

    GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertShader, 1, &vertSource, NULL);
    glCompileShader(vertShader);
    {
        GLint compiled;
        glGetShaderiv(vertShader, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLsizei len;
            glGetShaderiv(vertShader, GL_INFO_LOG_LENGTH, &len);

            GLchar* log = new GLchar[len + 1];
            glGetShaderInfoLog(vertShader, len, &len, log);
            std::cout << "Shader compilation failed: " << log << std::endl;
            delete[] log;
        }
    }
    glAttachShader(program, vertShader);

    // read fragment shader from Qt resource file
    QFile fragFile(fragf);
    fragFile.open(QFile::ReadOnly | QFile::Text);
    QString fragString;
    QTextStream fragStream(&fragFile);
    fragString.append(fragStream.readAll());
    std::string fragSTLString = fragString.toStdString();

    const GLchar* fragSource = fragSTLString.c_str();

    GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragShader, 1, &fragSource, NULL);
    glCompileShader(fragShader);
    {
        GLint compiled;
        glGetShaderiv(fragShader, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLsizei len;
            glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &len);

            GLchar* log = new GLchar[len + 1];
            glGetShaderInfoLog(fragShader, len, &len, log);
            std::cerr << "Shader compilation failed: " << log << std::endl;
            delete[] log;
        }
    }
    glAttachShader(program, fragShader);

    glLinkProgram(program);
    {
        GLint linked;
        glGetProgramiv(program, GL_LINK_STATUS, &linked);
        if (!linked) {
            GLsizei len;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);

            GLchar* log = new GLchar[len + 1];
            glGetProgramInfoLog(program, len, &len, log);
            std::cout << "Shader linker failed: " << log << std::endl;
            delete[] log;
        }
    }

    return program;
}

头文件:

#ifndef __GLWIDGET__INCLUDE__
#define __GLWIDGET__INCLUDE__

#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QMouseEvent>
#include <glm/glm.hpp>
#include <vector>

// glm by default uses degrees, but that functionality
// is deprecated so GLM_FORCE_RADIANS turns off some 
// glm warnings
#define GLM_FORCE_RADIANS

using glm::vec2;

class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core {
    Q_OBJECT

public:
    GLWidget(QWidget *parent = 0);
    ~GLWidget();

protected:
    void initializeGL();
    void resizeGL(int w, int h);
    void paintGL();

    void mousePressEvent(QMouseEvent *event);
    void keyPressEvent(QKeyEvent *event);

private:
    GLuint loadShaders(const char* vertf, const char* fragf);
    static const GLchar* readShader(const char* filename);

    GLuint vao;
    GLuint program;

    GLuint positionBuffer;
    GLint projectionMatrixLoc;

    bool outline;
    GLenum drawMode;

    glm::mat4 ortho;

    int next;

    std::vector<vec2> pts;
    int num_pts;
};

#endif

我的顶点着色器:

#version 330

in vec2 position;

uniform mat4 ProjectionMatrix;

void main() {
  gl_Position = vec4(position.x, position.y, 0, 1)*ProjectionMatrix;
}

我的片段着色器:

#version 330

out vec4 color_out;

void main() {
  color_out = vec4(1.0,1.0,1.0,1.0);
}

0 个答案:

没有答案