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