GLSL рендеринг в 2D - PullRequest
4 голосов
/ 20 июля 2011

(OpenGL 2.0)

Мне удалось сделать хороший рендеринг текста в opengl, и я решил сделать его шейдерным.Однако визуализированная текстура шрифта, которая выглядела хорошо в режиме фиксированного конвейера, выглядела неприятно в режиме GLSL.

В режиме фиксированного конвейера я не вижу никакой разницы между фильтрацией GL_LINEAR и GL_NEAREST, потому что текстура не нужнадействительно фильтровать, потому что я устанавливаю ортографическую проекцию и выравниваю ширину и высоту четырехугольника по координатам текстуры.

Теперь, когда я пытаюсь отрендерить его с помощью шейдера, я вижу очень плохие артефакты фильтрации GL_NEAREST, и дляGL_LINEAR текстура выглядит слишком размытой.

Фиксированный конвейер, удовлетворяющий требованиям, лучшее качество (без разницы между линейным / ближайшим):

GLSL, ближайший (видимые артефакты, например, посмотрите на дробьглифы):

enter image description here

GLSL, линейный (слишком размытый):

enter image description here

Программа шейдера:

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

В обоих случаях матрицы рассчитываются из одного и того же источника, хотя по соображениям производительности,как вы можете видеть, я записываю постоянные значения в код шейдера с помощью такой функции (если в этом причина, как мне их правильно написать?):

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

где "f"является некоторым двойным значением.

РЕДАКТИРОВАТЬ: Результат моих дальнейших исследований несколько удивителен.

Теперь я умножаю координаты вершины на ту же ортогональную матрицу наПроцессор (не в вершинном шейдере, как раньше), и я оставляю вершину нетронутой в вершинном шейдере, просто передавая ееgl_Position.Я не мог поверить, но это действительно работает и фактически решает мою проблему.Каждая операция выполняется с плавающей запятой, как в графическом процессоре.

Похоже, что умножение матрицы / вершины намного более точно на процессоре.вопрос: почему?

РЕДАКТИРОВАТЬ: На самом деле, вся причина была в разных матричных источниках ..!Действительно, очень маленькая ошибка!
Николь был ближайшим решением.

Ответы [ 2 ]

6 голосов
/ 20 июля 2011

хотя из соображений производительности, как вы можете видеть, я записываю постоянные значения в код шейдера

Это не поможет вашему выступлению. Загрузка единой матричной униформы довольно стандартна для большинства шейдеров OpenGL и ничего не будет стоить вам с точки зрения производительности.

Похоже, что умножение матрицы / вершины гораздо более точно на процессоре. вопрос: почему?

Это не точнее; это просто использование другой матрицы. Если вы передадите эту матрицу в GLSL через форму шейдера, вы, вероятно, получите тот же результат. Матрица, которую вы используете в шейдере, - это не та матрица, которую вы использовали в CPU.

3 голосов
/ 20 июля 2011

Мне кажется, проблема в смещении на полпикселя.

Посмотрите на: http://drilian.com/2008/11/25/understanding-half-pixel-and-half-texel-offsets/

Вы можете попробовать:

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

пока.

...