Пиксельное идеальное наложение текстур с помощью современного OpenGL - PullRequest
6 голосов
/ 23 апреля 2011

После того, как я решил попробовать программировать в современном OpenGL, я оставил конвейер с фиксированными функциями, и я не совсем уверен, что получу ту же функциональность, что и раньше.

Я пытаюсь текстурировать картуквадраты с идеальным размером пикселя, соответствующие размеру текстуры.Например, текстура 128x128 отображается на четырехугольник размером 128x128.

Это мой вершинный шейдер.


    #version 110
    uniform float xpos;
    uniform float ypos;
    uniform float tw; // texture width in pixels
    uniform float th; // texture height in pixels
    attribute vec4 position;
    varying vec2 texcoord;        
void main()
    {
    mat4 projectionMatrix = mat4( 2.0/600.0, 0.0, 0.0, -1.0,
                                  0.0, 2.0/800.0, 0.0, -1.0,
                                  0.0, 0.0, -1.0, 0.0,
                                  0.0, 0.0, 0.0, 1.0); 

    gl_Position = position * projectionMatrix;
    texcoord = (gl_Position.xy);
    }

Это мой фрагментный шейдер:


    #version 110
    uniform float fade_factor;    
    uniform sampler2D textures[1];
    varying vec2 texcoord;

    void main()
    {
        gl_FragColor = texture2D(textures[0], texcoord);
    }

Мои данные вершин таковы, где w и h - ширина и высота текстуры.


    [
     0, 0,
     w, 0,
     w, h,
     0, h
    ]

Я загружаю текстуру 128x128, и с этими шейдерами я вижу изображение, повторенное 4 раза: http://i.stack.imgur.com/UY7Ts.jpg

Может ли кто-нибудь дать совет о том, как правильно переводить и масштабировать, учитывая форму thth, xpos, xpos?

1 Ответ

6 голосов
/ 23 апреля 2011

Есть проблема с этим:

mat4 projectionMatrix = mat4( 2.0/600.0, 0.0, 0.0, -1.0,
                                  0.0, 2.0/800.0, 0.0, -1.0,
                                  0.0, 0.0, -1.0, 0.0,
                                  0.0, 0.0, 0.0, 1.0); 

gl_Position = position * projectionMatrix;

Матрицы преобразования являются ассоциативными справа, т.е. вы должны умножить в обратном порядке. Также вы обычно не указываете матрицу проекции в шейдере, вы передаете ее как униформу. OpenGL предоставляет вам готовые формы для проекции и просмотра моделей. В ядре OpenGL-3 вы можете повторно использовать унифицированные имена для обеспечения совместимости.

// predefined by OpenGL version < 3 core:
#if __VERSION__ < 400
uniform mat4 gl_ProjectionMatrix;
uniform mat4 gl_ModelviewMatrx;
uniform mat4 gl_ModelviewProjectionMatrix; // premultiplied gl_ProjectionMatrix * gl_ModelviewMatrix
uniform mat4 gl_ModelviewInverseTranspose; // needed for transformin normals

attribute vec4 gl_Vertex;

varying vec4 gl_TexCoord[];
#endif 

void main()
{
     gl_Position = gl_ModelviewProjectionMatrix * gl_Vertex;
}

Далее вы должны понимать, что координаты текстуры не относятся к пикселям текстуры (текселям), но что текстуру следует понимать как интерполирующую функцию с заданными точками выборки; Координаты текстуры 0 или 1 не попадают в центры текселя, но лежат точно между обтеканием, поэтому размываются. Пока ваш квад по размеру экрана точно соответствует размеру текстуры, это нормально. Но как только вы захотите показать только подизображения, вещи станут интересными (я оставляю читателю в качестве упражнения выяснение точного отображения; подсказка: у вас будут термины 0.5 / измерение и (измерение - 1) / измерение в растворе)

...