Мне нужна помощь, пытаясь переместить мой круг с матрицей просмотра. Я могу расположить круг, но не могу его переместить. Как я могу это сделать?
Прямо сейчас ограничивающий прямоугольник перемещается, но не круг.
Я пытался центрировать круг в прямоугольнике, но это не работает.
Любая помощь приветствуется!
#include <glew.h>
#include "circle.h"
Circle::Circle()
{
const std::string vertexShaderSource = R"END(
#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 position, vec2 texCoords>
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
void main()
{
gl_Position = projection * view * model * vec4(vertex.xy, 0.0, 1.0);
}
)END";
const std::string fragmentShaderSource = R"END(
#version 330 core
out vec4 color;
uniform vec2 dim;
uniform vec2 pos;
/**
* Convert r, g, b to normalized vec3
*/
vec3 rgb(float r, float g, float b) {
return vec3(r / 255.0, g / 255.0, b / 255.0);
}
/**
* Draw a circle at vec2 `pos` with radius `rad` and
* color `color`.
*/
vec4 circle(vec2 uv, vec2 pos, float rad, vec3 color) {
float d = length(pos - uv) - rad;
float t = clamp(d, 0.0, 1.0);
return vec4(color, 1.0 - t);
}
void main() {
vec2 uv = gl_FragCoord.xy;
float radius = 60;
vec2 center = pos;
// Background layer
vec4 layer1 = vec4(rgb(210.0, 222.0, 228.0), 0.3);
// Circle
vec3 red = rgb(225.0, 95.0, 60.0);
vec4 layer2 = circle(uv, center, radius, red);
// Blend the two
color = mix(layer1, layer2, layer2.a);
}
)END";
shader.Compile(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
// Configure VAO etc..
}
void Circle::Update(float deltaTime, int width, int height)
{
// Activate shader
shader.Activate();
auto camera = Services::Get<RenderService>()->camera;
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view;
if (skipPan == false)
{
view = camera.GetViewMatrix();
}
else
{
view = glm::mat4{1.0f};
}
projection = glm::ortho(0.0f, static_cast<float>(width),
static_cast<float>(height), 0.0f, -1.0f, 1.0f);
model = glm::translate(model, glm::vec3(transform.position.x, transform.position.y, 0.0f));
model = glm::scale(model, glm::vec3(transform.dimension.width, transform.dimension.height, 1.0f));
shader.setMat4("projection", projection);
shader.setMat4("model", model);
shader.setMat4("view", view);
shader.setVec2("dim", glm::vec2{transform.dimension.width, transform.dimension.height});
shader.setVec2("pos", glm::vec2{transform.position.x, transform.position.y});
shader.setVec4("spriteColor", glm::vec4{style.Background.r, style.Background.g, style.Background.b, style.Background.a});
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
Это проблема, с которой я уже некоторое время борюсь. Это относится и к другим фигурам, которые рендерятся с помощью SDF и тому подобного.
// configure VAO/VBO
const float vertices[] = {
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f};
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
Задаю этот вопрос, причина вижу только одна glBindVertexArray
Да, два объекта принадлежат одному и тому же массиву вершин.
так что проблема только с вашим массивом, который смущает gl_Position
Хм, ты прав. но я не уверен, как это исправить.
можете ли вы подтвердить после звонка useProgram
, вы связали атрибут pos
с помощью метода glGetAttribLocation
? а также подтвердите, что вы используете glGetUniformLocation
для привязки glUniformMatrix
Нет, я не связывал атрибут pos с этим методом. Я думал, что мне не нужно, так как я использую униформу.
Давайте продолжим обсуждение в чате.
Почему uv = gl_FragCoord.xy
? почему не координаты uv от вершин? (gl_MultiTexCoord0; или из вершинного шейдера, который является повсеместно распространенным методом). Используя gl_FragCoord, вы непреднамеренно сделали то, что предлагает этот ответ . Но на самом деле вам нужно противоположное тому, что там предлагается, то есть просто используйте координаты UV-текстуры обычным способом. Не волнуйся, ты не первый
Вы говорите, что пытаетесь переместить круг с матрицей вида. Вы действительно передаете эту матрицу своему вершинному шейдеру и используете ее при вычислении gl_Position
. Однако ваш расчет фрагментного шейдера основан на gl_FragCoord
и никоим образом не включает матрицу представления. Помните, что gl_FragCoord
— это координаты фрагмента относительно нижнего левого угла фреймбуфера (обычно), и поэтому на него не влияют преобразования модели/вида/проекции.
Чтобы решить эту проблему, вы можете выполнить одно из следующих действий:
Вычислите координаты фрагмента центра вашего круга в Circle::Update
и передайте их униформе pos
:
glm::vec4 pos = view*glm::vec4{transform.position.x, transform.position.y, 0.0f, 1.0f};
shader.setVec2("pos", pos.xy);
Примените преобразование области просмотра во фрагментном шейдере — то же самое, что и выше, но делается в шейдере. Это довольно некрасиво, поскольку вы применяете view
, но не model
, потому что последнее уже учтено в значении pos
. Также это требует больше вычислений во фрагментном шейдере.
Измените свой фрагментный шейдер, чтобы он работал с текстурными координатами вместо gl_FragCoord
. Если вы установите фиксированные координаты текстуры в вершинах четырехугольника, то интерполированные координаты внутри четырехугольника будут корректно преобразовываться в отношении любого вида/модели/проекции, таким образом обрабатывая масштабирование или даже перспективные проекции из коробки. Это, вероятно, будет самым аккуратным решением в вашем случае. (При этом растеризация на основе gl_FragCoord
иногда необходима, чтобы избежать артефактов на стыке между двумя треугольниками четырехугольника.)
Спасибо за ваш ответ. Я выбрал вариант № 3, и теперь он работает как шарм!
можете ли вы подтвердить
glDrawArrays
достаточно одного звонка? для двух объектов принадлежат ли эти два объекта одному массиву?