У меня есть очень простой движок, основанный на OpenGL, который может рендерить многоугольники любого цвета в окно с изменяемыми размерами.Сейчас я пытаюсь реализовать матрицы для своих шейдеров, передавая матрицы модели, перспективы и представления в виде униформы через мой шейдер.Перед добавлением униформы все работало как надо, я мог даже передать униформу vec2
для имитации источника света в положении моей мыши.Унифицированные mat4
s не работают так же хорошо, как vec2
s.
. В целях отладки я рендую только один желтый квадрат с центром на экране.При использовании без формы квадрат показывает, как ожидалось.теперь я пытаюсь передать один 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())));
Гдеx
и y
- координаты мышки.Затем я добавляю строку
uniform vec2 light_pos;
к фрагментному шейдеру.Это работает без проблем и отлично отслеживает мышь.Функция, используемая для установки униформы mat4
, выглядит так же, как и функция для установки униформы vec2
, разница только в 4fv для mat4
и 2f для vec2
.
.видите, я использую 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;
В целом мой вопрос сводится к тому, почему значения единого mat4 неправильно, есть ли способ узнать, что это за значения, и что я должен изменить в коде, чтобы заставить работать единообразный mat4s?
Пожалуйста, запросите любую дополнительную информацию, необходимую для ответа, я с удовольствиемпредоставьте все, что я забыл включить.