繁体   English   中英

用投影矩阵移动圆

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM