现代OpenGL中的像素完美纹理映射

6
在决定尝试现代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,th,xpos,xpos统一中进行翻译和缩放的建议吗?


你好,Lefty!欢迎来到 StackOverflow。请记住一些事项- 请使用四个空格或使用“{}”图标缩进代码,以便正确格式化。另外,在发布 OpenGL 标签时,指定你的 OpenGL 版本会很有帮助。特别是因为你的代码示例听起来像 OpenGL 2.0,这确实很有用,但现在并不是真正的“现代”。 :) - Kos
感谢回复。这是现代OpenGL(>= 3?),因为我没有使用固定功能管线,我的顶点数据是通过数组提供的,并且纹理采样是使用着色器完成的。话虽如此,我对此还是相对较新的,如果我有错误,请指正 :) - Lefty
与OpenGL相关:GPU供应商之间的确定性渲染 - Ciro Santilli OurBigBook.com
1个回答

7

这个有问题:

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

首先,您必须了解纹理坐标不是针对纹理像素(texels)的,而应将纹理视为具有给定采样点的插值函数;纹理坐标0或1不会命中texel的中心,而是恰好位于环绕之间,从而模糊。 只要您的屏幕上的四边形大小与纹理尺寸完全匹配,这就没问题。 但是,一旦您想要显示子图像,事情就变得有趣了(我将其留给读者作为练习来确定精确映射的方法;提示:解决方案中将有术语0.5 / dimension和(dimension-1)/ dimension)


这道与编程有关的问题对你来说很容易,DW! :O - Fattie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接