Search code examples
c#openglopentk

OpenGL - Maintain texture width to height ratio


I have a 256x256 crate texture and a plane twice as long as it is high.

I'd like to maintain the texture's aspect ratio and control it's scaling factor, rather than stretch it to all corners as shown below.

enter image description here

This is my object data:

// Vertex Positions
Vector3 vertices = new Vector3[] {
            new Vector3( 1,  0,  1),
            new Vector3( 3,  0,  1),
            new Vector3( 3,  1,  1),
            new Vector3( 1,  1,  1)};

// Index Order
int[] indices = new int[] {0, 1, 2,   0, 2, 3};

// Texture Co-ordinates
Vector2 texcoords = new Vector2[] {
            new Vector2 (0.0f, 0.0f),
            new Vector2 (1.0f, 0.0f),
            new Vector2 (1.0f, 1.0f),
            new Vector2 (0.0f, 1.0f)};

// Normals
Vector3 normals = new Vector3[] {
            new Vector3 (0.0f, 0.0f, 1.0f),
            new Vector3 (0.0f, 0.0f, 1.0f),
            new Vector3 (0.0f, 0.0f, 1.0f),
            new Vector3 (0.0f, 0.0f, 1.0f)};

I have enabled texture repeating with the following:

GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, Convert.ToInt32(TextureWrapMode.Repeat));
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, Convert.ToInt32(TextureWrapMode.Repeat));

By matching the texture co-ordinates to the plane's height and width, the texture does repeat as intended.

// Texture Co-ordinates
Vector2 texcoords = new Vector2[] {
            new Vector2 (0.0f, 0.0f),
            new Vector2 (2.0f, 0.0f),
            new Vector2 (2.0f, 1.0f),
            new Vector2 (0.0f, 1.0f)};

However, I'd like for all 256x256 textures to display consistent in size, regardless of the plane size.


Solution

  • Adjust your texture coordinates based on your aspect ratio.

    For instance, if your tile has a 2:1 (width:height) aspect, your texture coordinates will range from 0-2 on X rather than 0-1. This will cause the texture to tile twice in X.

    You'll need to check to see if X is greater than Y or visa-versa. If the former, scale your X by quadWidth / quadHeight. Otherwise, scale texCoord.y by quadHeight / quadWidth.

    That way, your smallest dimension will go from 0-1, and the larger dimension will adjust to match your texture aspect.

    You could just pass in the texture width and height (or aspect ratio, but width and height are pretty useful at times, so I just send them separately in a float2 uniform as x and y, respectively) to your shader, and do the correction there.

    Additional comments from OP:

    This worked. By calculating the width of the plane (x2 - x1) and a texture offset (x1 % 1), the textures now align horizontally to a "world grid".

    // Texture Co-ordinates
    Vector2 texcoords = new Vector2[] {
        new Vector2 (TextureOffset, 0.0f),
        new Vector2 (TextureOffset + Width, 0.0f),
        new Vector2 (TextureOffset + Width, 1.0f),
        new Vector2 (TextureOffset, 1.0f)};
    

    enter image description here