OpenGL - Use non normalized texcoords

2019-09-07 00:25发布

问题:

By default, OpenGL uses normalized TexCoords, which mean the value must be between 0 and 1 ([0..1]). the common implementation of Vertex must be look something like this:

        // Common Implementation of Vertex
        Vertex v = new Vertex(
            // Position
            new Vector2(0f, 500f), 
            // 'Normalized' TexCoords [0..1]
            new Vector2(0f, 1f), 
            // Color of Vertex
            Color.White
        );

        // Or in immediate mode..
        // It's the same, we still need to specify between 0 and 1 ([0..1])
        GL.TexCoord2(1f, 0f);

However, is it possible to use non normalized texcoord (so it specified in pixel format, which mean the value must be between 0 and size ([0..size])) in OpenGL?

回答1:

To set up the texture transformation for this case, use:

glMatrixMode(GL_TEXTURE);
glScalef(1.0f / textureWidth, 1.0f / textureHeight, 1.0f);

It looks like you made attempts to do the same thing with glOrtho(). While that's possible, the following will not give the desired result:

glOrtho(0.0, textureWidth, 0.0, textureHeight, ...);

glOrtho() builds a matrix that transforms the given ranges to the range [-1.0, 1.0] in both coordinate directions. This makes sense because it is mostly used for vertex coordinates that need to be transformed into NDC space, which is [-1.0, 1.0].

However, for texture coordinates, you want to transform the [0.0, textureWidth] and [0.0, textureHeight] ranges to the range [0.0, 1.0]. If you were completely set on using glOrtho(), the correct call would be:

glOrtho(-textureWidth, textureWidth, -textureHeight, textureHeight, 1.0, -1.0);

Since this now maps [-textureWidth, textureWidth] to [-1.0, 1.0], this means that it maps [0.0, textureWidth] to [0.0, 1.0], which is the desired transformation.

But it's much easier and cleaner to use the glScalef() call shown at the start of my answer.



回答2:

I still can't figure out why GL.Ortho (while in MatrixMode.Texture) isn't give me intended result..

So finally, I ended up with calculating matrix manually:

        // Initialize identity matrix
        Matrix4 matrix = new Matrix4
                         (1f, 0f, 0f, 0f,
                          0f, 1f, 0f, 0f,
                          0f, 0f, 1f, 0f,
                          0f, 0f, 0f, 1f);

        // Or use Matrix4.Identity (in OpenTK case), that should be equal(?)

        // Convert to normalized
        matrix[0, 0] = 1f / textureWidth;
        matrix[1, 1] = 1f / textureHeight;

        // Apply the matrix to texture matrix
        GL.MatrixMode(MatrixMode.Texture);
        GL.LoadMatrix(ref matrix);


标签: c# opengl opentk