跳轉到內容

OpenGL 程式設計/超取樣

來自華夏公益教科書,開放世界開放書籍
普通。
抗鋸齒。

在白色背景上繪製一條黑色線條時,計算機或 GPU 在最基本層面上只會確定應該將哪些畫素設定為黑色。這對於水平或垂直線條非常有效。然而,如果線條是斜線,你將立即看到線條不平滑,而是鋸齒狀的。然而,如果我們不僅使用黑色和白色,而且還策略性地放置灰色畫素,我們就可以欺騙我們的眼睛,使線條看起來更加平滑。這被稱為抗鋸齒。有各種方法可以對線條、其他形狀甚至文字進行抗鋸齒。最古老的技巧是在放大兩倍的情況下繪製線條,然後將得到的黑白影像縮小到原始大小,取每個 2x2 畫素組的平均值。結果影像將有 5 種灰色陰影(包括黑色和白色),並且是一個很大的改進。當然,你也可以將線條放大三倍、四倍甚至更多倍(對於 10、17 或更多種灰色陰影)。這種技術被稱為超取樣。它非常耗時,因為你必須渲染更大的影像,而且它只提供有限數量的陰影。然而,它最大的優點是這種技術非常簡單,並且適用於 *任何* 型別的影像,無論是線條、文字還是 3D 場景。

使用累積緩衝區進行超取樣

[編輯 | 編輯原始碼]

我們可以使用累積緩衝區實現相同的技術。然而,問題是累積緩衝區不比普通的顏色緩衝區大,它的大小完全相同。相反,我們可以多次渲染同一個場景,但每次都稍微偏移一點。假設我們從以下設定模型-檢視-投影矩陣並渲染幀的程式碼開始

glm::mat4 modelview = glm::lookAt(...);
glm::mat4 projection = glm::perspective(...);
glm::mat4 mvp = projection * modelview;
glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, glm::value_ptr(mvp));
draw_scene();
glSwapBuffers();

如果我們想要進行 2x2 抗鋸齒,我們分別將場景偏移 (0, 0)、(0.5, 0)、(0, 0.5) 和 (0.5, 0.5) 個畫素。這很容易做到;在我們對頂點應用模型-檢視-投影矩陣之後,我們有了螢幕座標,其中 (0, 0) 對應於視窗的左下角,(1, 1) 對應於視窗的右上角。因此,為了偏移 (0.5, 0.5) 個畫素,我們需要應用 (0.5 / w, 0.5 / h) 個單位的平移,其中 w 和 h 是視窗的寬度和高度(以畫素為單位)。這就是結果

glm::mat4 modelview = glm::lookAt(...);
glm::mat4 projection = glm::perspective(...);

for(int i = 0; i < 4; i++) {
  glm::vec3 shift = glm::vec3((i % 2) * 0.5 / w, (i / 2) * 0.5 / h, 0);
  glm::mat4 aa = glm::translate(glm::mat4(1.0f), shift);
  glm::mat4 mvp = aa * projection * modelview;
  glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, glm::value_ptr(mvp));
  draw_scene();
  glAccum(i ? GL_ACCUM : GL_LOAD, 0.25);
}

glAccum(GL_RETURN, 1);
glSwapBuffers();
  • 將此技術應用於任何之前的教程。
  • 嘗試 3x3、4x4、8x8 和 16x16 畫素抗鋸齒。你認為在質量上沒有提升的點在哪裡?
  • 這真的與渲染更大的影像然後縮小它相同嗎?那麼小於一個畫素的線條呢?
  • 你可以將此技術與運動模糊有效地結合起來嗎?
華夏公益教科書