Search code examples
javaopengltexturesrenderinglwjgl

Textured triangle, rendering only one color


In this example i try to render a simple textured triangle in java with lwjgl, but i simply can't figure out why it render the triangle filled with one color.

The color seems to be the average color of the whole texture or just one pixel of the texture, if i make the image for example green it renders the triangle green.

Thanks in advance for you help.

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.system.MemoryUtil.*;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import org.joml.Matrix4f;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWWindowSizeCallback;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;

import de.matthiasmann.twl.utils.PNGDecoder;
import de.matthiasmann.twl.utils.PNGDecoder.Format;

public class TEST
{
    public int WIDTH = 1000;
    public int HEIGHT = 1000;
    public float vertices[] = new float[]
    {
            //COORDINATES
            0.0f, 0.8f, 0.0f,1.0f,
            //COLOR NOT USED
            0.0f,1.0f,0.0f,1.0f,
            //TEXTURE COORDINATES
            0.5f, 1.0f,

            //COORDINATES
            -0.8f,-0.8f, 0.0f,1.0f,
            //COLOR NOT USED
            1.0f,0.0f,0.0f,1.0f,
            //TEXTURE COORDINATES
            0.0f, 0.0f,

            //COORDINATES
            0.8f,-0.8f, 0.0f,1.0f,
            //COLOR NOT USED
            0.0f,0.0f,1.0f,1.0f,
            //TEXTURE COORDINATES
            1.0f, 0.0f
    };

    public TEST()
    {

    }


    public int start() throws IOException
    {
        glfwInit();
        glfwDefaultWindowHints(); 
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GL11.GL_TRUE);
        long window = glfwCreateWindow(WIDTH, HEIGHT, "HAHA", NULL, NULL);

        glfwMakeContextCurrent(window);
        glfwSwapInterval(1);
        glfwShowWindow(window);
        GL.createCapabilities();

        //CALLBACKS
        GLFWKeyCallback keycallback = new GLFWKeyCallback()
        {

            @Override
            public void invoke(long window, int key, int scancode, int action, int mods)
            {
                if(key==GLFW_KEY_ESCAPE&&action==GLFW_PRESS)
                {
                    glfwSetWindowShouldClose(window, GLFW_TRUE);
                }
            }
        };
        glfwSetKeyCallback(window,keycallback );
        GLFWErrorCallback errorcallback = new GLFWErrorCallback()
        {

            @Override
            public void invoke(int error, long description)
            {
                System.out.println("ERROR CODE: " + error + "  ERROR DESCRITPION: "+description);
            }
        };
        glfwSetErrorCallback(errorcallback);
        GLFWWindowSizeCallback windowsizecallback = new GLFWWindowSizeCallback()
        {
            @Override
            public void invoke(long window, int width, int height)
            {
                glViewport(0, 0, width, height);
                System.out.println(width+"    "+height);
            }
        };
        glfwSetWindowSizeCallback(window, windowsizecallback);



        //////////////////////////
        int VAO = glGenVertexArrays();
        glBindVertexArray(VAO);


        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * Float.BYTES);
        byteBuffer.order(ByteOrder.nativeOrder());
        FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
        floatBuffer.clear();
        floatBuffer.put(vertices);
        floatBuffer.flip();

        int VBO = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, floatBuffer, GL_STATIC_DRAW);

        glVertexAttribPointer(0, 4, GL_FLOAT, false, 40, 0);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(1, 4, GL_FLOAT, false, 40, 16);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(2, 2, GL_FLOAT, false, 40, 24);
        glEnableVertexAttribArray(2);

        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glBindVertexArray(0);
        ///////////////////////
        ///////////////////////
        LoadFile loader = new LoadFile("res/shader.vs", "res/shader.frag");

        int vertexshader = glCreateShader(GL_VERTEX_SHADER);
        int fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);

        glShaderSource(vertexshader, loader.readVertex());
        glShaderSource(fragmentshader, loader.readFragment());

        glCompileShader(vertexshader);
        glCompileShader(fragmentshader);

        System.out.println(glGetShaderInfoLog(vertexshader));
        System.out.println(glGetShaderInfoLog(fragmentshader));


        int program = glCreateProgram();

        glAttachShader(program, vertexshader);
        glAttachShader(program, fragmentshader);

        glLinkProgram(program);

        glDeleteShader(vertexshader);
        glDeleteShader(fragmentshader);

        System.out.println(glGetProgramInfoLog(program));
        ///////////////////////////

        int texture1 = glGenTextures();
        InputStream texture1inputstream = new FileInputStream("res/container2.png");
        PNGDecoder texture1decoder = new PNGDecoder(texture1inputstream);
        ByteBuffer texture1buffer = ByteBuffer.allocateDirect(4*texture1decoder.getWidth()*texture1decoder.getHeight()).order(ByteOrder.nativeOrder());
        texture1decoder.decode(texture1buffer, texture1decoder.getWidth()*4, Format.RGBA);
        texture1buffer.flip();

        glBindTexture(GL_TEXTURE_2D, texture1);

        glTexImage2D
        (
                GL_TEXTURE_2D,
                0,
                GL_RGBA,
                texture1decoder.getWidth(),
                texture1decoder.getHeight(),
                0,
                GL_RGBA,
                GL_UNSIGNED_BYTE,
                texture1buffer
        );

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

        glBindTexture(GL_TEXTURE_2D, 0);

        int textureloc = glGetUniformLocation(program, "texture");

        //MAKE UNIFORM SETTER
        UniformSetter uniformsetter = new UniformSetter(program, "model", "projection","view");
        /////////////////////

        glEnable(GL_DEPTH_TEST);

        boolean running=true;

        while(running&&glfwWindowShouldClose(window)==GLFW_FALSE)
        {
            glfwPollEvents();
            glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
            glClearColor(1.0f, 0.0f, 0.0f, 1.0f);

            glUseProgram(program);

            glBindVertexArray(VAO);
            ///////////////////////

            for(int a = 0;a<4;a++)
            {
                //MAKE MATRIX MODEL
                Matrix4f model = new Matrix4f();

                model.translate(0.0f,0.0f,0.0f);
                float xang = 0f;
                float yang = 0f;
                float zang = 0f;
                model.rotate((float) Math.toRadians(xang), 1.0f, 0.0f, 0.0f);
                model.rotate((float) Math.toRadians(yang), 0.0f, 1.0f, 0.0f);
                model.rotate((float) Math.toRadians(zang), 0.0f, 0.0f, 1.0f);
                model.scale(0.5f);

                uniformsetter.setModel(model);
                ////////////////////

                //MAKE MATRIX VIEW
                Matrix4f view = new Matrix4f();

                view.lookAt(0.0f, 0.0f, 1.0f,
                            0.0f, 0.0f, 0.0f,
                            0.0f, 1.0f, 0.0f);

                uniformsetter.setView(view);
                //////////////////

                //MAKE MATRIX PROJECTION
                Matrix4f projection = new Matrix4f();

                projection.ortho(-1.0f, 1.0f, -1.0f, 1.0f,1.0f,-1.0f);

                uniformsetter.setProjection(projection);
                /////////////////////////

                //ACTIVATE AND BIND TEXTURE
                glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_2D, texture1);
                glUniform1i(textureloc, 0);

                ///////////////////////////

                glDrawArrays(GL_TRIANGLES, 0, 3);

                glBindTexture(GL_TEXTURE_2D, 0);
            }

            ///////////////////////
            glBindVertexArray(0);

            glUseProgram(0);

            glfwSwapInterval(1);
            glfwSwapBuffers(window);
        }

        System.out.println(glGetError());
        glfwTerminate();

        return 0;
    }
}

Vertex Shader:

#version 440
layout (location = 0) in vec4 position;
//NOT USED layout (location = 1) in vec4 colorin;
layout (location = 2) in vec2 texturecoordiantesin;

//NOT USED out vec4 colorout;
out vec2 texturecoordinatesout;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection*view*model*position;
    //NOT USED colorout=colorin;
}

Fragment Shader:

#version 440
out vec4 color;

//NOT USED in vec4 colorout;
in vec2 texturecoordinatesout;
uniform sampler2D texture;

void main()
{
    color = texture2D(texture,texturecoordinatesout);
}

Solution

  • Your are missing the propagation of the texturecoordinatesin in the vertex shader. Add this anywhere in the vertex shader:

    texturecoordinatesout = texturecoordinatesin;
    

    Also, you are doing a mistake when you set the vertex array pointer. The last parameter of glVertexAttribPointer for attribute 2 should be 32. 4 floats offset for position and 4 floats offset for color is a total of 8 floats offset, or 32 bytes:

        glVertexAttribPointer(0, 4, GL_FLOAT, false, 40, 0);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(1, 4, GL_FLOAT, false, 40, 16);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(2, 2, GL_FLOAT, false, 40, 32);
        glEnableVertexAttribArray(2);