像素完美纹理映射与现代OpenGL

时间:2011-04-23 13:11:37

标签: opengl glsl texture-mapping shader

在决定尝试使用现代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

任何人都可以提供有关正确的方法的建议,以便能够翻译和缩放给定的tw,xpos,xpos制服吗?

1 个答案:

答案 0 :(得分:6)

这有一个问题:

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;

转换matices是右关联的,即你应该乘以相反的顺序。此外,您通常不在着色器中指定投影矩阵,将其作为制服传递。 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)/维度的术语在解决方案中)