Mk3Y
Mk3Y

Reputation: 1

LWJGL Texture loading / mapping issue

I'm drawing a quad with a 512 x 512 texture composed of 4 squares with 4 different colors (yellow, blue, green, red). When i look at the image it's all yellow but the tex coords space from 0 to 1 and i'm quite sure they're mapped correctly... here's the code:

private void loadTexture(String textureFile) {
        TexHandle = glGenTextures();
        BufferedImage TextureBuffer = null;
        try {
            TextureBuffer = ImageIO.read(new File(textureFile));
        } catch (IOException ex) {
            System.err.println("Error while reading the texture: " + textureFile);
            System.exit(1);
        }
        Width = TextureBuffer.getWidth();
        Height = TextureBuffer.getHeight();
        AlphaChannel = TextureBuffer.getColorModel().hasAlpha();
        int pixel;
        int[] pixels = TextureBuffer.getRGB(0, 0, Width, Height, null, 0, Width);
        ByteBuffer Buffer = BufferUtils.createByteBuffer(Width * Height * 4);
        for(int i = 0; i < Height; i++){
            for(int j = 0; j < Width; j++){
                pixel = pixels[i * Width + j];

                Buffer.put((byte)( pixel        & 0xff));
                Buffer.put((byte)((pixel >> 8)  & 0xff));
                Buffer.put((byte)((pixel >> 16) & 0xff));

                if(AlphaChannel)
                    Buffer.put((byte)((pixel >> 24) & 0xff));
                else
                    Buffer.put((byte)0xff);
            }
        }
        glBindTexture(GL_TEXTURE_2D, TexHandle);

        Buffer.flip();
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, Buffer);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        glBindTexture(GL_TEXTURE_2D, 0);
    }

public void initOpenGL() {
        glClearColor(0f, 0f, 0.4f, 1f);

        glFrontFace(GL_CCW);

        glCullFace(GL_BACK);
        glEnable(GL_CULL_FACE);

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);

        glDepthFunc(GL_LEQUAL);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_DEPTH_CLAMP);

        glEnable(GL_TEXTURE_2D);
    }

main :

    while(!window.isClosing()){

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        program.updateUniform("TextureIndex", 0);
        glActiveTexture(GL_TEXTURE0 + 0);
        glBindTexture(GL_TEXTURE_2D, TexHandle);
        glBegin(GL_QUADS);
        glNormal3f(0, 0, 0);

        glTexCoord2f(0, 0);
        glVertex3f(-.5f, -.5f, -2f);

        glTexCoord2f(1, 0);
        glVertex3f(.5f, -.5f, -2f);

        glTexCoord2f(1, 1);
        glVertex3f(.5f, .5f, -2f);

        glTexCoord2f(0, 1);
        glVertex3f(-.5f, .5f, -2f);

        glEnd();

        window.update();
    }

vertex :

layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 in_texture_coord;
layout(location = 2) in vec3 in_normal;
out vec2 out_texture_coord;

void main(){

    gl_Position = vec4(in_position, 1.0);
    out_texture_coord  = in_texture_coord;

}

fragment :

    out vec4 out_color;
    in vec2 in_texture_coord; // passed from the vertex shader
    uniform sampler2D TextureIndex;

    void main(){

        out_color = texture2D(TextureIndex, in_texture_coord);

    }

Upvotes: 0

Views: 111

Answers (2)

Mk3Y
Mk3Y

Reputation: 1

The problem was the naming of the variable: in VS i have "out vec3 out_tex_coord" while in FS i have "in vec3 in_tex_coord" and because they didnt match the UVs of the texture where always (0,0).

Upvotes: 0

Reto Koradi
Reto Koradi

Reputation: 54592

The posted code is mixing legacy OpenGL functionality with modern OpenGL functionality in unsupported ways. The vertex specification code uses old style fixed function attributes:

glNormal3f(0, 0, 0);
glTexCoord2f(0, 0);
glVertex3f(-.5f, -.5f, -2f);

While the vertex shader expects generic vertex attributes:

layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 in_texture_coord;
layout(location = 2) in vec3 in_normal;

There is no direct correspondence between the two. The spec has some language saying that generic attribute 0 maps to the legacy vertex position, but even that does not always work reliably with all drivers. And it is certainly invalid to assume that for example values specified with glTexCoord2f() will map to an attribute with (location = 1) in the vertex shader.

There are two main ways to fix that:

  1. Change the shader code to work with the legacy calls used for specifying the vertex data. This is done by removing the in variable declarations in the vertex shader code, and using the pre-defined variables to access the attribute values:

    gl_Vertex for the vertex position

    gl_MultiTexCoord0 for the texture coordinates

    gl_Normal for the normal

  2. Use API functions for setting the values of generic vertex attributes instead of the fixed function attributes. For the code fragment above, and matching the locations from the vertex shader code:

    glVertexAttrib3f(2, 0.0f, 0.0f, 0.0f);
    glVertexAttrib2f(1, 0.0f, 0.0f);
    glVertexAttrib3f(0, -0.5f, -0.5f, -2.0f);
    

If you're ready to move towards modern OpenGL, option 2 will be the better direction. One of the next steps on that path would be to use vertex buffer objects (VBO) to specify the vertex data, instead of the immediate mode calls in your current code.

Upvotes: 2

Related Questions