簡體   English   中英

GLSL 2D 渲染

[英]GLSL rendering in 2D

(OpenGL 2.0)

我設法在 opengl 中進行了一些不錯的文本渲染,並決定將其設為着色器設計。 然而,在固定管道模式下看起來不錯的渲染字體紋理在 GLSL 模式下看起來令人不快。

在固定管道模式下,我看不到 GL_LINEAR 和 GL_NEAREST 過濾之間有任何區別,這是因為紋理實際上不需要過濾,因為我設置了正交投影並將四邊形的寬度和高度與紋理坐標對齊。

現在,當我嘗試使用着色器對其進行渲染時,我可以看到一些非常糟糕的 GL_NEAREST 過濾偽影,並且對於 GL_LINEAR,紋理顯得過於模糊。

固定管道,令人滿意,質量最好(線性/最近沒有區別):

GLSL,最近(可見偽影,例如,查看分數字形):

在此處輸入圖像描述

GLSL,線性(太模糊):

在此處輸入圖像描述

着色器程序:

Vertex shader was successfully compiled to run on hardware.
Fragment shader was successfully compiled to run on hardware.
Fragment shader(s) linked, vertex shader(s) linked. 

------------------------------------------------------------------------------------------
 attribute vec2 at_Vertex;
 attribute vec2 at_Texcoord;
 varying vec2 texCoord;


 void main(void) {
     texCoord = at_Texcoord;
    gl_Position = mat4(0.00119617, 0, 0, 0, 0, 0.00195503, 0, 0, 0, 0, -1, 0, -1, -1, -0, 1)* vec4(at_Vertex.x, at_Vertex.y, 0, 1);
}

-----------------------------------------------------------------------------------------
 varying vec2 texCoord;
 uniform sampler2D diffuseMap;
 void main(void) {
     gl_FragColor = texture2D(diffuseMap, texCoord); 
 }

四渲染,固定:

    glTexCoord2f (0.0f, 0.0f);
            glVertex2f (40.0f, 40.0f);
            glTexCoord2f (0.0f, 1.0f);
            glVertex2f ((font.tex_r.w+40.0f), 40.0f);
            glTexCoord2f (1.0f, 1.0f);
            glVertex2f ((font.tex_r.w+40.0f), (font.tex_r.h+40.0f));
            glTexCoord2f (1.0f, 0.0f);
            glVertex2f (40.0f,              (font.tex_r.h+40.0f));

四邊形渲染,着色器模式:

            glVertexAttrib2f(__MeshShader::ATTRIB_TEXCOORD, 0.0f, 0.0f);
            glVertexAttrib2f(__MeshShader::ATTRIB_VERTEX, 40.0f, 40.0f);
            glVertexAttrib2f(__MeshShader::ATTRIB_TEXCOORD, 0.0f, 1.0f);
            glVertexAttrib2f(__MeshShader::ATTRIB_VERTEX, (font.tex_r.w+40.0f), 40.0f);
            glVertexAttrib2f(__MeshShader::ATTRIB_TEXCOORD, 1.0f, 1.0f);
            glVertexAttrib2f(__MeshShader::ATTRIB_VERTEX, (font.tex_r.w+40.0f), (font.tex_r.h+40.0f));
            glVertexAttrib2f(__MeshShader::ATTRIB_TEXCOORD, 1.0f, 0.0f);
            glVertexAttrib2f(__MeshShader::ATTRIB_VERTEX, 40.0f,                (font.tex_r.h+40.0f));

在這兩種情況下,矩陣都是從同一個源計算的,盡管出於性能原因,如您所見,我在 function 的幫助下將常量值寫入着色器代碼(如果這是原因,我該怎么寫他們正確嗎?):

std::ostringstream buffer;
    buffer << f;
    return buffer.str().c_str();

其中“f”是一些雙值。

編輯:我進一步研究的結果有點令人驚訝。

現在我將頂點坐標乘以 CPU 上的相同正交矩陣(而不是像以前那樣在頂點着色器中),並且我在頂點着色器中保持頂點不變,只是將它傳遞給 gl_Position。 我簡直不敢相信,但這確實有效並且實際上解決了我的問題。 每個操作都是在浮點數上進行的,如 GPU。

似乎矩陣/頂點乘法在 CPU 上更准確。 問題是:為什么?

編輯:實際上,整個原因是不同的矩陣來源..,真的,真的很小的錯誤!
Nicol 最接近解決方案。

盡管出於性能原因,如您所見,我將常量值寫入着色器代碼

這不會幫助你的表現。 對於大多數 OpenGL 着色器來說,上傳單個矩陣制服是相當標准的,並且在性能方面不會花費你任何重要的成本。

似乎矩陣/頂點乘法在 CPU 上更准確。 問題是:為什么?

這不是更准確; 它只是使用不同的矩陣。 如果您通過着色器制服將該矩陣傳遞給 GLSL,您可能會得到相同的結果。 您在着色器中使用的矩陣與您在 CPU 上使用的矩陣不同。

我認為問題在於半像素偏移。

看: http://drilian.com/2008/11/25/understanding-half-pixel-and-half-texel-offsets/

你可以試試:

texCoord = at_Texcoord + vec2(0.5,0.5) / textureSize(diffuseMap,0);

再見。

暫無
暫無

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

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