[英]Move circle with Projection matrix
我需要一些帮助来尝试使用视图矩阵移动我的圆圈。 我可以 position 圆但不能移动它。 我怎样才能做到这一点?
现在边界矩形移动但不是圆。
我试图将圆圈置于矩形的中心,但这不起作用。
任何帮助表示赞赏!
#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);
您说您正在尝试使用view matrix移动圆圈。 您确实将该矩阵传递给顶点着色器,并在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
的光栅化有时是必要的,以避免四边形的两个三角形之间的接缝处出现伪影。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.