簡體   English   中英

OpenGL:如何修復矩形中缺少的角像素(線或線循環)

[英]OpenGL: How to fix missing corner pixel in rect (lines or line loop)

看一下中間綠色矩形的左下角:

在此處輸入圖像描述

他們在左下角少了一個像素。

在此處輸入圖像描述

我畫的是這樣的:

class Rect: public StaticModel {
  public:
    Rect() {  
        constexpr glm::vec2 vertices[] {
                {-0.5,0.5},  // top left
                {0.5,0.5},  // top right
                {0.5,-0.5},  // bottom right
                {-0.5,-0.5},  // bottom left
        };
        _buf.bufferData<glm::vec2>(vertices,BufferUsage::StaticDraw);
        _idxBuf.bufferData<GLuint>({0,1,3,2,0,3,1,2},BufferUsage::StaticDraw);
    }

    void bind() const override {
        _buf.bindVertex(); 
        _idxBuf.bind();
    }

    void draw() const override {
        gl::drawElements(8,DrawMode::Lines);
    }

  private:
    VertexBuffer _buf{sizeof(glm::vec2)};
    ElementArrayBuffer _idxBuf{};
};

該代碼使用了一堆我的輔助方法/類,但您應該能夠知道它的作用。 我嘗試使用簡單的 GL_LINE_LOOP 繪制矩形,但有同樣的問題,所以現在我正在嘗試 GL_LINES 並在同一方向繪制所有線條:從上到下和從左到右,但即使我仍然缺少一個像素.

這些坐標正在通過正交投影:

gl_Position = projection * model * vec4(inPos, 0.0, 1.0);

所以着色器將那些 0.5 坐標縮放到像素坐標,但我不認為這是一個舍入錯誤。

還有什么我可以嘗試讓那個角落對齊的嗎?

OpenGL 為實現如何光柵化線提供了很多余地。 它需要一些理想的屬性,但在混合 x 主要(“水平”)和 y 主要(“垂直”)線時,這些屬性並不能防止出現間隙。

  • 首先,“規范的精神”是光柵化半開線; 即包括第一個頂點並排除最后一個頂點。 出於這個原因,您應該確保每個頂點恰好出現一次作為源和一次作為目標:

     _idxBuf.bufferData<GLuint>({0,1,1,2,2,3,3,0},BufferUsage::StaticDraw);

    這與您嘗試“從上到下,從左到右”繪制相反。

    GL_LINE_LOOP已經這樣做了,你說它不能解決問題。 這確實不能保證解決問題,因為您在這里混合了 x-major 和 y-major 行,但是您仍然應該遵循規則以便下一點起作用。

  • 接下來,我敢打賭,你的一些頂點正好落在像素之間; 即 window 坐標小數部分正好為零。 當光柵化這些原語時,不同實現之間的差異(或者在我們的例子中,在同一實現上的 x 主線和 y 主線之間)變得很突出。

    要解決這個問題,您可以將頂點捕捉到像素網格:

     // xy - vertex in window coordinates, ie same as gl_FragCoord xy = floor(xy) + 0.5

    您可以在 C++ 或頂點着色器中執行此操作。 無論哪種情況,您都需要應用投影和視口轉換,然后撤消它們,以便 OpenGL 之后可以重新應用它們。 這很丑,我知道。

然而,光柵化像素完美線的唯一防彈方法是渲染三角形以覆蓋形狀(每條線單獨或整個矩形)並從片段着色器中的gl_FragCoord.xy分析計算覆蓋率。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM