简体   繁体   中英

GLSL rendering in 2D

(OpenGL 2.0)

I managed to do some nice text-rendering in opengl, and decided to make it shader-designed. However, rendered font texture that looked nice in fixed pipeline mode looked unpleasant in GLSL mode.

In fixed pipeline mode, I don't see any difference between GL_LINEAR and GL_NEAREST filtering, it's because the texture doesn't need to filter really, because I set orthographic projection and align quad's width and height to the texture coordinates.

Now when I'm trying to render it with shader, i can see some very bad GL_NEAREST filtering artifacts, and for GL_LINEAR the texture appears too blurry.

Fixed pipeline, satysfying, best quality (no difference between linear/nearest):

GLSL, nearest (visible artifacts, for example, look at fraction glyphs):

在此处输入图像描述

GLSL, linear (too blurry):

在此处输入图像描述

Shader program:

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); 
 }

Quad rendering, fixed:

    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));

Quad rendering, shader-mode:

            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));

In both cases the matrices are calculated from the same source, though for performance reasons, as you can see, I'm writing constant values into the shader code with the help of such a function (if that is the reason, how do I write them properly? ):

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

where "f" is some double value.

EDIT: Result of my further research is a little bit surprising.

Now I'm multiplying vertex coordinates by the same orthogonal matrix on CPU (not in vertex shader like before) and I'm leaving the vertex untouched in vertex shader, just passing it to the gl_Position. I couldn't believe, but this really works and actually solves my problem. Every operation is made on floats, as in GPU.

Seems like matrix/vertex multiplication is much more accurate on CPU. question is: why?

EDIT: Actually, whole reason was different matrix sources.., Really, really small bug!
Nicol was nearest the solution.

though for performance reasons, as you can see, I'm writing constant values into the shader code

That's not going to help your performance. Uploading a single matrix uniform is pretty standard for most OpenGL shaders, and will cost you nothing of significance in terms of performance.

Seems like matrix/vertex multiplication is much more accurate on CPU. question is: why?

It's not more accurate; it's simply using a different matrix. If you passed that matrix to GLSL via a shader uniform, you would probably get the same result. The matrix you use in the shader is not the same matrix that you used on the CPU.

I think the problem is the half-pixel offset.

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

You can try:

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

bye.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM