c++ - 由 glUniformMatrix4fv 创建时,统一 mat4 具有未知值

标签 c++ opengl glsl shader glm-math

我有一个基于 OpenGL 的非常基本的引擎,可以将任何颜色的多边形渲染到可调整大小的窗口。我现在正在尝试通过我的着色器将模型、透视和 View 矩阵作为制服来为我的着色器实现矩阵。在添加 uniform 之前一切正常,我什至可以传入一个 uniform vec2 来模拟鼠标位置处的光源。统一的 mat4 不如 vec2 好。

出于调试目的,我只渲染了一个位于屏幕中心的黄色方 block 。当不使用制服时,正方形会按预期显示。我现在尝试传入一个 mat4,设置为单位矩阵。在顶点着色器中,我将 gl_Position 乘以我制服的单位矩阵。当我运行该程序时,它只显示一个黑色窗口。

我已经尝试在顶点着色器中手动创建单位矩阵并将 gl_Position 乘以该矩阵而不是统一矩阵。当我这样做时,我的黄色方 block 显示正常。这让我相信统一的 mat4 没有得到正确的值,但是,我不知道如何在着色器中使用矩阵时检查它的值。

这是我的顶点着色器的样子:

#version 430 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;

out vec4 Color;

uniform mat4 model;
uniform mat4 view;
uniform mat4 project;

void main()
{
    mat4 id;
    id[0] = vec4(1.0, 0.0, 0.0, 0.0);
    id[1] = vec4(0.0, 1.0, 0.0, 0.0);
    id[2] = vec4(0.0, 0.0, 1.0, 0.0);
    id[3] = vec4(0.0, 0.0, 0.0, 1.0);
    Color = color;
    gl_Position = id * vec4(position, 1.0);
}

mat4 id 是手动创建的单位矩阵,当将 id * 更改为 model * 我得到黑色窗口。

这是我的片段着色器的样子:

#version 430 core

in vec4 Color;

out vec4 outColor;

void main()
{
    outColor = Color;
}

着色器由这段代码初始化:

m_shaderID = glCreateProgram();

const char* vertexSource = ReadFile::readFile(vertpath);
const char* fragmentSource = ReadFile::readFile(fragpath);

GLint status;

// Vertex Shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
    std::cout << "Failed to compile vertex shader!\nInfo log: " << std::endl;
    char buffer[512];
    glGetShaderInfoLog(vertexShader, 512, NULL, buffer);
    std::cout << buffer << std::endl;
    glDeleteShader(vertexShader);
}

// Fragment Shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
    std::cout << "Failed to compile fragment shader!\nInfo log: " << std::endl;
    char buffer[512];
    glGetShaderInfoLog(fragmentShader, 512, NULL, buffer);
    std::cout << buffer << std::endl;
    glDeleteShader(fragmentShader);
}

// Shader program
glAttachShader(m_shaderID, vertexShader);
glAttachShader(m_shaderID, fragmentShader);
glLinkProgram(m_shaderID);
glValidateProgram(m_shaderID);

glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);

矩阵由这段代码创建为统一:

void Shader::setUniformmat4(const GLchar* name, glm::mat4 matrix)
{
    for (int i = 0; i <= 3; i++)
        printf("%f, %f, %f, %f\n", matrix[i].x, matrix[i].y, matrix[i].z, matrix[i].w);
    glUniformMatrix4fv(glGetUniformLocation(m_shaderID, name), 1, GL_FALSE, glm::value_ptr(matrix));
}

printf 用于检查用于创建制服的矩阵的值,并且它们在该点具有单位矩阵的值。

此代码调用函数 setUniformmat4:

glm::mat4 model = glm::mat4(1.0);
shader.setUniformmat4("model", model);

创建灯光效果时,我通过调用此函数创建制服:

void Shader::setUniformvec2(const GLchar* name, glm::vec2 vector)
{
    glUniform2f(glGetUniformLocation(m_shaderID, name), vector.x, vector.y);
}

通过这段代码:

shader.setUniformvec2("light_pos", glm::vec2((x / window.getWidth()) * 2.0 - 1.0, 1.0 - 2.0 * (y / window.getHeight())));

其中 xy 是鼠标坐标。然后我添加行

uniform vec2 light_pos;

到片段着色器。这没有问题,并且可以完美地跟踪鼠标。用于设置uniform mat4 的函数看起来与设置uniform vec2 的函数相同,唯一不同的是mat4 的4fv 和2f 代表 vec2

如您所见,我对矩阵和 vector 使用 glm。

我的主要功能是这样的:

    Window window(720, 720, "Window");

    Shader shader("shader.vert", "shader.frag");

    glm::mat4 model = glm::mat4(1.0);
    shader.setUniformmat4("model", model);

    Renderer* renderer = new Renderer();

    std::vector<StaticSprite*> sprites;

    sprites.push_back(new StaticSprite(-0.5, -0.5, 0.0, 1.0, 1.0, glm::vec4(1.0, 1.0, 0.0, 1.0), &shader));

    while (!window.closed())
    {
        window.clear();
        shader.enable();
        double x, y;
        window.getMousePosition(x, y);
        shader.setUniformvec2("light_pos", glm::vec2((x / window.getWidth()) * 2.0 - 1.0, 1.0 - 2.0 * (y / window.getHeight())));

        for (StaticSprite* sprite : sprites)
            renderer->submit(sprite);
        renderer->flush();

        shader.disable();
        window.update();
    }
    return 0;

我总结的问题基本上是为什么 uniform mat4 的值不正确,有什么方法可以找出这些值是什么,我应该在代码中更改什么以使 uniform mat4 工作?

请询问提供答案所需的任何其他信息,我很乐意提供我忘记包含的任何信息。

最佳答案

glUniform*为当前程序对象指定统一变量的值。这意味着该程序必须由 glUseProgram 安装之前:

Shader shader("shader.vert", "shader.frag");

shader.enable(); // <--- this is missing

glm::mat4 model = glm::mat4(1.0);
shader.setUniformmat4("model", model);

事件程序资源可以从不是“当前”程序的程序对象中获取(例如 glGetUniformLocation )。注意,程序对象是glGetUniformLocation的一个参数。
但是通过 glUniform* 来设置统一的值, 该程序必须是当前安装的程序。

关于c++ - 由 glUniformMatrix4fv 创建时,统一 mat4 具有未知值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54388831/

相关文章:

c++ - OpenGl:glRotatef 机制以及如何在不移动的情况下围绕自身旋转正方形

opengl - 如何在立方体上获得平坦的法线

c++ - OpenGL 代码不是每次都显示相同的东西吗?

c++ - 为什么我的函数不返回正确的输出?

c++ - 为构造函数重用可变参数模板

c++ - 访问 range_expression 内的嵌套元素返回不完整的映射(段错误)

c++ 字符数组是否超出范围?

c++ - Mac OSX 10.9 中的 Glut 弃用,IDE : QT Creator

opengl - OpenGL 和 GLSL 中的 glTexParameter 和过滤?

opengl - 在什么时候将纹理用于颜色托盘而不是着色器切换语句更有效?