由glUniformMatrix4fv

时间:2019-01-27 13:49:55

标签: c++ opengl glsl shader glm-math

我有一个非常基本的基于OpenGL的引擎,可以将任何颜色的多边形渲染到可调整大小的窗口中。我现在正在尝试通过着色器为模型,透视图和视图矩阵提供统一形式,以为着色器实现矩阵。在添加制服之前,一切都可以正常工作,我什至可以通过制服vec2来模拟鼠标位置的光源。统一的mat4不能像vec2那样工作。

出于调试目的,我仅在屏幕上居中绘制一个黄色正方形。不使用制服时,正方形显示为预期。我现在尝试传递一个mat4,设置为一个单位矩阵。在顶点着色器中,我将gl_Position乘以统一的单位矩阵。当我运行该程序时,它仅显示一个黑色窗口。

我尝试在顶点着色器中手动创建一个单位矩阵,并将gl_Position乘以该矩阵,而不是统一矩阵。当我这样做时,我的黄色方块显示为正常。这使我相信统一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;

到片段着色器。这没有问题,并且可以完美地跟踪鼠标。用于设置统一mat4的功能看起来与用于设置统一vec2的功能相同,唯一的区别是mat4的4fv和{​​{1}}的2f。

如您所见,我正在将glm用于矩阵和向量。

我的主要功能如下:

vec2

我总结的问题基本上是为什么统一的mat4的值不正确,有什么办法找出那些值是什么,我应该在代码中进行哪些更改以使统一的mat4s工作?

请要求提供答案的任何其他信息,我会很乐意提供我忘了包含的任何内容。

1 个答案:

答案 0 :(得分:4)

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*设置统一值,该程序必须是当前安装的程序。