c++ - 使用 glUniformMatrix4fv() 用新矩阵更新旧矩阵?

标签 c++ opengl glfw

我在用新矩阵更新旧矩阵时遇到问题,因为我正在从 WebGL 过渡到 OpenGL,当我想用​​键操作转换对象时,它开始变得令人生畏,问题是当我想做的时候新的翻译,新的矩阵应该被更新并且提供给顶点着色器的数据(uniform u_matrix)也应该被改变,但它没有。

为了展示这个问题,我把它简化了,我用一个平移矩阵画了一次,在 sleep (2)之后,我又画了一次但是用了一个不同的平移矩阵,再睡 2 秒看看结果,问题是矩阵在第二阶段根本没有更新,根本没有变化。

matC.translate(nb1, nb2, nb2) 通过返回指向存储在堆栈中的 16' 值一维数组的第一个值的指针来很好地工作。

#include <GL/glew.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <assert.h>
#include <unistd.h>
#include "./../Matrix/main.cpp";
using namespace std;

GLuint prog_hdlr;
GLint   a_position;

const int SCREEN_WIDTH  = 1024;
const int SCREEN_HEIGHT = 1024;

// float * translation = matC.translation(0.2, 0, 0);
// float * rotationX;
// float * rotationY;
// float * rotationZ;
// float translate = 0.01;

// float * tab4 = matC.multiplyMatrices(tab1, tab2);

static unsigned int CompileShader(unsigned int type, const string& source) {
    unsigned int id = glCreateShader(type);
    cout << source.c_str() << endl;
    const char * src = source.c_str();
    glShaderSource(id, 1, &src, NULL);
    glCompileShader(id);

    int result; 
    glGetShaderiv(id, GL_COMPILE_STATUS, &result);
    if(result == GL_FALSE) {
        std::cout << "failed to compile shader" << std::endl;
        GLint maxLength = 0;
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &maxLength);

        vector<GLchar> errorLog(maxLength);
        glGetShaderInfoLog(id, maxLength, &maxLength, &errorLog[0]);

        int iter;
        for (vector<GLchar>::const_iterator iter = errorLog.begin(); iter != errorLog.end(); ++iter)
            cout << *iter;

        glDeleteShader(id);
    }
    return id;
}

static int CreateProgram(const string& vertexShader, const string& fragmentShader) {
    unsigned int program = glCreateProgram();
    unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

    glAttachShader(program, vs);
    glAttachShader(program, fs);
    glLinkProgram(program);
    glValidateProgram(program);

    glDetachShader(program,vs);
    glDetachShader(program,fs);
    glDeleteShader(vs); 
    glDeleteShader(fs);

    return program;
}

void input(GLFWwindow * window, int key, int action, int u, int i) {
   // switch(key) {
   //    case GLFW_KEY_W : {
   //       translate += 0.1;
   //       translation = matC.translation(translate, 0, 0);
   //    };
   //    case GLFW_KEY_A : {

   //    };
   //    case GLFW_KEY_S : {
   //       translate -= 0.1;
   //       translation = matC.translation(translate, 0, 0);
   //    };
   //    case GLFW_KEY_D : {

   //    };
   // };
}

int main(int argc, char * argv) {
    glutInit(&argc, &argv);
    GLFWwindow * window;

    cout << glGetString(GL_VERSION) << endl;

    if(!glfwInit())
        return -1;

    window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Triangle rendering", NULL, NULL);
    if(!window) {
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    if(glewInit() != GLEW_OK) {
        std::cout << "error..!!" << std::endl;
    }

    float positions[108] = {
      -0.5f, -0.5f, 0.0f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.0f,
      0.5f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f,

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

      -0.5f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f, -0.5f, 0.5f, -1.0f,
      -0.5f, 0.5f, -1.0f, -0.5f, -0.5f, -1.0f, -0.5f, -0.5f, 0.0f,

      0.5f, -0.5f, 0.0f, 0.5f, 0.5f, -1.0f, 0.5f, 0.5f, 0.0f,
      0.5f, 0.5f, -1.0f, 0.5f, -0.5f, 0.0f, 0.5f, -0.5f, -1.0f,

      -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, -1.0f, -0.5f, 0.5f, -1.0f,
      0.5f, 0.5f, -1.0f, -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 1.0f, 

      -0.5f, -0.5f, 0.0f, -0.5f, -0.5f, -1.0f, 0.5f, -0.5f, -1.0f,
      0.5f, -0.5f, -1.0f, 0.5f, -0.5f, 1.0f, -0.5f, -0.5f, 0.0f
    };

    float colors[108] = {
      1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f,
      1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f,

      0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  1.0f, 0.0f,
      0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  1.0f, 0.0f,

      0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
      0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,

      1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,  1.0f, 1.0f, 0.0f,
      1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,  1.0f, 1.0f, 0.0f,

      0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,  1.0f, 1.0f,
      0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,  1.0f, 1.0f,

      1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
      1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
    };

    string vertexShader = R"(
      #version 130
      attribute vec4 a_position;
      attribute vec3 a_color;
      varying vec3 v_color;
      uniform mat4 u_matrix;
      void main() {
         mat4 a_matrix;
         a_matrix = mat4(1.0f);
         vec4 pos = u_matrix*a_position;
         gl_Position = vec4(pos.xyz, 1.0);
         v_color = a_color;
      }
   )";

    string fragmentShader = R"(
      #version 130
      varying vec3 v_color;
      void main() {
         gl_FragColor = vec4(v_color, 1.0);
      }
    )";


    unsigned int program = CreateProgram(vertexShader, fragmentShader);
    glUseProgram(program);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    GLint attributePositionLocation = glGetAttribLocation(program, "a_position");
    GLint uniformMatrixLocation = glGetUniformLocation(program, "u_matrix");
    GLint attributeColorLocation = glGetAttribLocation(program, "a_color");

    unsigned int buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, 108*sizeof(float), positions, GL_STATIC_DRAW);

    glEnableVertexAttribArray(attributePositionLocation);
    glVertexAttribPointer(attributePositionLocation, 3, GL_FLOAT, GL_FALSE, 0, NULL);

    unsigned int bufferColor;
    glGenBuffers(1, &bufferColor);
    glBindBuffer(GL_ARRAY_BUFFER, bufferColor);
    glBufferData(GL_ARRAY_BUFFER, 108*sizeof(float), colors, GL_STATIC_DRAW);

    glEnableVertexAttribArray(attributeColorLocation);
    glVertexAttribPointer(attributeColorLocation, 3, GL_FLOAT, GL_FALSE, 0, NULL);

    glfwSetKeyCallback(window, input);

    // while(!glfwWindowShouldClose(window)) {
    //     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //     glUniformMatrix4fv(uniformMatrixLocation, 1, GL_FALSE, translation);
    //     glDrawArrays(GL_TRIANGLES, 0, 36);
    //     glfwSwapBuffers(window);
    //     glfwPollEvents();
    // }

    Matrix matC = Matrix();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glUniformMatrix4fv(uniformMatrixLocation, 1, GL_FALSE, matC.translation(0.5, 0.5, 0));
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glfwSwapBuffers(window);
    glfwPollEvents();

    sleep(2);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glUniformMatrix4fv(uniformMatrixLocation, 1, GL_FALSE, matC.translation(-0.5, -0.5, 0));
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glfwSwapBuffers(window);
    glfwPollEvents();

    sleep(2);

    glfwTerminate();
    return 0;
}

在 WebGL 中它完美地工作:

function drawScene(gl) {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    gl.uniformMatrix4fv(whateverMatrixLocation, false, whateverMatrix);
    gl.drawArrays(gl.TRIANGLES, 0, whateverNumber);

    requestAnimationFrame(drawScene.bind(this, gl));
}

我做错了什么?我正在使用 GLSL 1.3 版...?

编辑:

class Matrix {
public:

    Matrix() {};

    static float * translation(float x, float y, float z) {
        static float tab[16] = {
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            x, y, z, 1
        };
        return tab;
    }
}

最佳答案

static 初始化程序只运行一次,而不是每次都通过函数。您可以切换到 std::array 并每次通过以下方式分配新值:

class Matrix
{
public:
    float* translation( float x, float y, float z )
    {
        static std::array< float, 16 > tab;
        tab =
        {
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            x, y, z, 1
        };
        return tab.data();
    }
};

或者使用GLM :)

关于c++ - 使用 glUniformMatrix4fv() 用新矩阵更新旧矩阵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49260349/

相关文章:

c++ - 模板参数 - 指向模板化类型的指针

c++ - 这段代码中的数组初始化风格是什么?是标准的吗?

c++ - glfwSwapInterval(1) 无法启用 vsync?

c++ - OpenGL GLFW 构建错误或链接错误

c++ - 转发声明问题

c++ - 将 return 替换为标准输入的选项卡

c++ - OpenGL 与 FBO RTT,在不该混合的时候混合

c++ - 加强文件完整性

c++ - 为什么我在屏幕上显示了一半的三角形?

c++ - 通过顶点属性指针将颜色坐标传递到顶点着色器