使用现代 OpenGL 进行像素完美纹理映射

发布于 2024-11-03 04:06:56 字数 1318 浏览 4 评论 0原文

在决定尝试使用现代 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 次:https://i.sstatic。 net/UY7Ts.jpg

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

After deciding to try programming in modern OpenGL, I've left behind the fixed function pipeline and I'm not entirely sure about getting the same functionality I had before.

I'm trying to texture map quads with pixel perfect size, matching the texture size. For example, a 128x128 texture maps to a quad 128x128 in size.

This is my vertex shader.


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

This is my fragment shader:


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

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

My vertex data is as such, where w and h are the width and height of the texture.


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

I load a 128x128 texture and with these shaders I see the image repeated 4 times: https://i.sstatic.net/UY7Ts.jpg

Can anyone offer advice on the correct way to be able to translate and scale given the tw th, xpos, xpos uniforms?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

Saygoodbye 2024-11-10 04:06:56

这有一个问题:

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 不会击中纹素的中心,而是恰好位于环绕之间,因此会模糊。只要屏幕上的四边形尺寸与纹理尺寸完全匹配就可以了。但是,一旦您只想显示子图像,事情就会变得有趣(我将其作为练习留给读者来找出确切的映射;提示:您将拥有术语 0.5/dimension 和 (dimension - 1)/dimension在溶液中)

There's a problem with this:

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;

Transformation matices are right associative, i.e. you should multiply the opposite order. Also you normally don't specify a projection matrix in the shader, you pass it as a uniform. OpenGL provides you ready to use uniforms for projection and modelview. In OpenGL-3 core you can reuse the uniform names to stay compatible.

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

Next you must understand that texture coordinates don't address texture pixels (texels), but that the texture should be understood as a interpolating function with the given sampling points; texture coordinates 0 or 1 don't hit the texel's centers, but lie exactly between the wraparound, thus blurring. As long as your quad on screen size exactly matches the texture dimensions this is fine. But as soon as you want to show just a subimage things get interesting (I leave it as an exercise to the reader to figure out the exact mapping; hint: You'll have the terms 0.5/dimension and (dimension - 1)/dimension in the solution)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文