簡體   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