c++openglglfw

Weird OpenGL Texture Display


I am drawing a 3D cube with texture and i get sth like this. I dont exactly know what is wrong ;/ https://i.sstatic.net/081nl.png

Vectors for texturecord

    vec2(0.0f, 0.0f),
    vec2(1.0f, 0.0f),
    vec2(1.0f, 1.0f),
    vec2(0.0f, 1.0f),

....
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 9));
....
glUniform1i(glGetUniformLocation(program, "mySampler"), 0);
....
color = texture(myTextureSampler,UV); //SHADER CODE

To load first example i used:

SDL_Surface* textures;
textures = SDL_LoadBMP(filename);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, textures->w, textures->h, 0, GL_RGB, GL_UNSIGNED_BYTE, textures->pixels);

To second pics i used :

int width, height;
    GLubyte * data;
    FILE * file;
    file = fopen(filename, "rb");
    if (file == NULL) return 0;
    width = 128;
    height = 128;
    data = (GLubyte *)malloc(width * height * 3);
    //int size = fseek(file,);
    fread(data, width * height * 3, 1, file);
    fclose(file);
    for (int i = 0; i < width * height; ++i)
    {
        int index = i * 3;
        unsigned char B, R;
        B = data[index];
        R = data[index + 2];

        data[index] = R;
        data[index + 2] = B;
    }
    glActiveTexture(GL_TEXTURE0);
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, data);

The both doesnt work correct;// any ideas?

Complete program:

main.cpp:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <GL\glew.h> // UP
#include <GL\glut.h>
#include <GLFW\glfw3.h>
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtx\transform.hpp>
#include <SDL.h>

using namespace glm;

GLuint LoadTexture(const char * filename)
{
    int width, height;
    GLubyte * data;
    FILE * file;
    file = fopen(filename, "rb");
    if (file == NULL) return 0;
    width = 128;
    height = 128;
    data = (GLubyte *)malloc(width * height * 3);
    //int size = fseek(file,);
    fread(data, width * height * 3, 1, file);
    fclose(file);
    for (int i = 0; i < width * height; ++i)
    {
        int index = i * 3;
        unsigned char B, R;
        B = data[index];
        R = data[index + 2];

        data[index] = R;
        data[index + 2] = B;
    }

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glActiveTexture(GL_TEXTURE0);
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);

    //free(data);

    return texture;
    /**
    SDL_Surface* textures;
    textures = SDL_LoadBMP(filename);
    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, textures->w, textures->h, 0, GL_RGB, GL_UNSIGNED_BYTE, textures->pixels);
    return texture;
    **/
}
std::string LoadFileToString(const char* filepath){
    std::string fileData = "";
    std::ifstream stream(filepath, std::ios::in);

    if (stream.is_open()){
        std::string line = "";
        while (getline(stream, line)){
            fileData += "\n" + line;
        }
        stream.close();
    }
    return fileData;
}
GLuint LoadShaders(const char*VertShaderPath, const char* fragShaderPath){
    GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);

    std::string vertShaderSource = LoadFileToString(VertShaderPath);
    std::string fragShaderSource = LoadFileToString(fragShaderPath);

    const char*  rawVertShaderSource = vertShaderSource.c_str();
    const char*  rawfragShaderSource = fragShaderSource.c_str();

    glShaderSource(vertShader, 1, &rawVertShaderSource, NULL);
    glShaderSource(fragShader, 1, &rawfragShaderSource, NULL);

    glCompileShader(vertShader);
    glCompileShader(fragShader);

    GLuint program = glCreateProgram();
    glAttachShader(program, vertShader);
    glAttachShader(program, fragShader);
    glLinkProgram(program);

    return program;
}

const float movementspeed = 0.01f;
class Camera{
    vec3 position;
    vec3 viewDirection;
    const vec3 UP;
    vec2 oldmouseposition;
public:
    Camera();
    mat4 getWorldToViewMatrix() const;
    void mouseUpdate(const vec2 &newMousePosition);
    void moveForward();
    void moveBackWard();
    void left();
    void right();
    void up();
    void down();

};
Camera::Camera() :viewDirection(0.0f, 0.0f, -1.0f), UP(0.0f, 1.0f, 0.0f){}
void Camera::mouseUpdate(const vec2 &newMousePosition){

    glm::vec2 mouseDelta = newMousePosition - oldmouseposition;
    if (glm::length(mouseDelta) >10.0f)
    {
        oldmouseposition = newMousePosition;
        return;
    }
    viewDirection = glm::mat3(glm::rotate(-mouseDelta.x*0.5f, UP)) * viewDirection;
    oldmouseposition = newMousePosition;

}
void Camera::moveForward(){
    position -= movementspeed *viewDirection;
}
void Camera::moveBackWard(){
    position += movementspeed *viewDirection;
}
void Camera::left(){
    glm::vec3 strafeDirection = glm::cross(viewDirection, UP);
    position += movementspeed *strafeDirection;
}
void Camera::right(){
    glm::vec3 strafeDirection = glm::cross(viewDirection, UP);
    position += -movementspeed *strafeDirection;
}
void Camera::up(){
    position += movementspeed *UP;
}
void Camera::down(){
    position += -movementspeed *UP;
}
mat4 Camera::getWorldToViewMatrix() const {
    return lookAt(position, position - viewDirection, UP);
}


int main(int argc, char ** argv)
{
    if (!glfwInit())
        exit(EXIT_FAILURE);

    GLFWwindow* window;
    window = glfwCreateWindow(640, 480, "My 3D World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);
    glewExperimental = true;
    if (glewInit() != GLEW_OK){
        glfwTerminate();
        exit(EXIT_FAILURE);
    }
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    GLuint program = LoadShaders("vertex.wss", "fragment.fss"); // shadersprogram

    struct Vertex{
        glm::vec3 position;
        glm::vec3 color;
        glm::vec2 texture;
        glm::vec3 normal;
    };
    Vertex verts[] = {
        vec3(-1.0f, +1.0f, +1.0f), // 0
        vec3(0.0f, 1.0f, 0.0f), // Colour
        vec2(0.0f, 0.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(+1.0f, +1.0f, +1.0f), // 1
        vec3(0.0f, 0.0f, 1.0f), // Colour
        vec2(1.0f, 0.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(+1.0f, +1.0f, -1.0f), // 2
        vec3(1.0f, 0.0f, 0.0f), // Colour
        vec2(1.0f, 1.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(-1.0f, +1.0f, -1.0f), // 3
        vec3(0.0f, 0.0f, 0.0f), // Colour
        vec2(0.0f, 1.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal

        vec3(-1.0f, +1.0f, -1.0f), // 4
        vec3(0.0f, 1.0f, 0.0f), // Colour
        vec2(0.0f, 0.0f),
        vec3(0.0f, -1.0f, 0.0f), //normal
        vec3(+1.0f, +1.0f, -1.0f), // 5
        vec3(1.0f, 0.0f, 0.0f), // Colour
        vec2(1.0f, 0.0f),
        vec3(0.0f, -1.0f, 0.0f), //normal
        vec3(+1.0f, -1.0f, -1.0f), // 
        vec3(0.0f, 0.0f, 1.0f), // Colour
        vec2(1.0f, 1.0f),
        vec3(0.0f, -1.0f, 0.0f), //normal
        vec3(-1.0f, -1.0f, -1.0f), // 7
        vec3(0.0f, 1.0f, 0.0f), // Colour
        vec2(0.0f, 1.0f),
        vec3(0.0f, -1.0f, 0.0f), //normal

        vec3(+1.0f, +1.0f, -1.0f), // 8
        vec3(0.0f, 0.0f, 1.0f), // Colour
        vec2(0.0f, 0.0f),
        vec3(0.0f, 0.0f, -1.0f), //normal
        vec3(+1.0f, +1.0f, +1.0f), // 9
        vec3(0.0f, 1.0f, 0.0f), // Colour
        vec2(1.0f, 0.0f),
        vec3(0.0f, 0.0f, -1.0f), //normal
        vec3(+1.0f, -1.0f, +1.0f), // 10
        vec3(0.0f, 0.0f, 1.0f), // Colour
        vec2(1.0f, 1.0f),
        vec3(0.0f, 0.0f, -1.0f), //normal
        vec3(+1.0f, -1.0f, -1.0f), // 11
        vec3(0.0f, 0.0f, 1.0f), // Colour
        vec2(0.0f, 1.0f),
        vec3(0.0f, 0.0f, -1.0f), //normal

        vec3(-1.0f, +1.0f, +1.0f), // 12
        vec3(0.0f, 0.0f, 1.0f), // Colour
        vec2(0.0f, 0.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(-1.0f, +1.0f, -1.0f), // 13
        vec3(1.0f, 0.0f, 0.0f), // Colour
        vec2(1.0f, 0.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(-1.0f, -1.0f, -1.0f), // 14
        vec3(0.0f, 1.0f, 0.0f), // Colour
        vec2(1.0f, 1.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(-1.0f, -1.0f, +1.0f), // 15
        vec3(0.0f, 1.0f, 0.0f), // Colour
        vec2(0.0f, 1.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal

        vec3(+1.0f, +1.0f, +1.0f), // 16
        vec3(0.0f, 0.0f, 1.0f), // Colour
        vec2(0.0f, 0.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(-1.0f, +1.0f, +1.0f), // 17
        vec3(1.0f, 0.0f, 1.0f), // Colour
        vec2(1.0f, 0.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(-1.0f, -1.0f, +1.0f), // 18
        vec3(0.0f, 1.0f, 0.0f), // Colour
        vec2(1.0f, 1.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(+1.0f, -1.0f, +1.0f), // 19
        vec3(1.0f, 0.0f, 1.0f), // Colour
        vec2(0.0f, 1.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal

        vec3(+1.0f, -1.0f, -1.0f), // 20
        vec3(0.0f, 1.0f, 0.0f), // Colour
        vec2(0.0f, 0.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(-1.0f, -1.0f, -1.0f), // 21
        vec3(0.0f, 1.0f, 0.0f), // Colour
        vec2(1.0f, 0.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(-1.0f, -1.0f, +1.0f), // 22
        vec3(0.0f, 1.0f, 1.0f), // Colour
        vec2(1.0f, 1.0f),
        vec3(0.0f, 1.0f, 0.0f), //normal
        vec3(+1.0f, -1.0f, +1.0f), // 23
        vec3(1.0f, 1.0f, 0.0f), // Colour
        vec2(0.0f, 1.0f),
        vec3(0.0f, 1.0f, 0.0f) //normal
    };
    GLushort indices[] = {
        0, 1, 2, 0, 2, 3, // Top
        4, 5, 6, 4, 6, 7, // Front
        8, 9, 10, 8, 10, 11, // Right
        12, 13, 14, 12, 14, 15, // Left
        16, 17, 18, 16, 18, 19, // Back
        20, 22, 21, 20, 23, 22 // Bottom
    };
    ////////VAO niepotrzebne
    ////////VBO
    GLuint vboID;
    glGenBuffers(1, &vboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_DYNAMIC_DRAW);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);
    glEnableVertexAttribArray(3);
    GLuint indexbuff;
    glGenBuffers(1, &indexbuff);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
    //////


    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, LoadTexture("block"));

    Camera camera;

    while (!glfwWindowShouldClose(window))
    {
        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);



        glUseProgram(program);

        double xpos, ypos;
        glfwGetCursorPos(window, &xpos, &ypos);

        if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){
            camera.moveForward();
        }
        if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){
            camera.moveBackWard();
        }
        if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){
            camera.left();
        }
        if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS){
            camera.right();
        }
        if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS){
            camera.up();
        }
        if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS){
            camera.down();
        }
        if (xpos > 0 && xpos < 640 && ypos>0 && ypos < 400){
            camera.mouseUpdate(vec2(float(xpos / 50), float(ypos / 50)));
            std::cout << "pos x: " << xpos << "pos y: " << ypos << std::endl;
        }

        // textures
        glUniform1i(glGetUniformLocation(program, "mySampler"), 0);
        //AMBIENT LIGHT
        GLint ambientlightlocation = glGetUniformLocation(program, "ambientLight");
        vec3 ambientLight(0.3f, 0.3f, 0.3f);
        glUniform3fv(ambientlightlocation, 1, &ambientLight[0]);

        //Light
        GLint lightlocation = glGetUniformLocation(program, "lightPosition");
        vec3 lightposition(1.0f, 1.0f, -3.75f);
        glUniform3fv(lightlocation, 1, &lightposition[0]);


        GLint fullTransformMatrixUniformLocation = glGetUniformLocation(program, "fullTransformMatrix");
        mat4 fullTransformMatrix;
        mat4 projectionMatrix = perspective(90.0f, (480.0f / 640.0f), 0.1f, 5.0f);
        mat4 worldToProjectionMatrix = projectionMatrix* camera.getWorldToViewMatrix();

        //CUBE 1 tak sie robi gdyby sie roznily
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (void*)0);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 3));
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 6));
        glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 9));
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);

        mat4 cube1WorldMatrix = translate(vec3(1.0f, 0.0f, -3.75f)) * rotate(0.0f, vec3(0.0f, 1.0f, 1.0f));
        fullTransformMatrix = worldToProjectionMatrix *cube1WorldMatrix;
        glUniformMatrix4fv(fullTransformMatrixUniformLocation, 1, GL_FALSE, &fullTransformMatrix[0][0]);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);

        // CUBE 2 gdyby byly rozne 
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (void*)0);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 3));
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 6));
        glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 9));
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);

        mat4 cube2WorldMatrix = translate(vec3(-3.0f, 0.0f, -3.75f)) * rotate(126.0f, vec3(1.0f, 0.0f, 0.0f));
        fullTransformMatrix = worldToProjectionMatrix *cube2WorldMatrix;
        glUniformMatrix4fv(fullTransformMatrixUniformLocation, 1, GL_FALSE, &fullTransformMatrix[0][0]);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);


        glfwSwapBuffers(window);
        glfwPollEvents();

    }
    glfwDestroyWindow(window);
    glfwTerminate();
    exit(EXIT_SUCCESS);
}

fragment.fss:

#version 330 core
out vec4 color;

in vec3 theColor;
in vec2 UV;

uniform sampler2D myTextureSampler;

void main()
{
    color = texture(myTextureSampler,UV);
    //texture(myTextureSampler,UV);
    // * vec4(theColor,1.0);

}

vertex.wss:

#version 330 core

layout(location=0) in vec3 in_pos;
layout(location=1) in vec3 vertexColor;
layout(location=2) in vec2 vertexUV;
layout(location=3) in vec3 normal;

uniform mat4 fullTransformMatrix;


uniform vec3 ambientLight;
uniform vec3 lightPosition;

out vec3 theColor;
out vec2 UV;

void main()
{
    vec4 v = vec4(in_pos, 1.0);
    gl_Position = fullTransformMatrix* v;

    vec3 lightVector = normalize(lightPosition-normal);
    float brightness = dot(lightVector,normal);
    theColor = vertexColor * vec3( brightness, brightness, brightness);// * ambientLight;

    UV = vertexUV;
}

Solution

  • If you want to load compressed images you'll need a proper decoder.

    Your LoadTexture() function was assuming everything passed in is an uncompressed, tightly-packed blob of RGB triplets, which is...not a good assumption :)

    Here's an example using stb_image and a screenshot PNG:

    GLuint LoadTexture(const char * filename)
    {
        int width = 0, height = 0, n = 0;
        unsigned char* data = stbi_load
            (
            filename,
            &width,
            &height,
            &n,
            3
            );
    
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glActiveTexture(GL_TEXTURE0);
        GLuint texture;
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    
        stbi_image_free( data );
    
        return texture;
    }
    

    yo dawg!

    All together:

    #include <iostream>
    #include <cstdarg>
    
    #include <GL\glew.h>
    #include <GLFW\glfw3.h>
    
    #define GLM_FORCE_RADIANS
    #include <glm\gtc\matrix_transform.hpp>
    #include <glm\gtx\transform.hpp>
    
    #define STB_IMAGE_IMPLEMENTATION
    #include "stb_image.h"
    
    using namespace glm;
    
    struct Program
    {
        static GLuint Load( const char* shader, ... )
        {
            GLuint prog = glCreateProgram();
            va_list args;
            va_start( args, shader );
            while( shader )
            {
                const GLenum type = va_arg( args, GLenum );
                AttachShader( prog, type, shader );
                shader = va_arg( args, const char* );
            }
            va_end( args );
            glLinkProgram( prog );
            CheckStatus( prog );
            return prog;
        }
    
    private:
        static void CheckStatus( GLuint obj )
        {
            GLint status = GL_FALSE;
            if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
            if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
            if( status == GL_TRUE ) return;
            GLchar log[ 1 << 15 ] = { 0 };
            if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
            if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
            std::cerr << log << std::endl;
            exit( EXIT_FAILURE );
        }
    
        static void AttachShader( GLuint program, GLenum type, const char* src )
        {
            GLuint shader = glCreateShader( type );
            glShaderSource( shader, 1, &src, NULL );
            glCompileShader( shader );
            CheckStatus( shader );
            glAttachShader( program, shader );
            glDeleteShader( shader );
        }
    };
    
    #define GLSL(version, shader) "#version " #version "\n" #shader
    
    const char* vert = GLSL
    (
        330 core,
        layout(location=0) in vec3 in_pos;
        layout(location=1) in vec3 vertexColor;
        layout(location=2) in vec2 vertexUV;
        layout(location=3) in vec3 normal;
    
        uniform mat4 fullTransformMatrix;
    
        uniform vec3 ambientLight;
        uniform vec3 lightPosition;
    
        out vec3 theColor;
        out vec2 UV;
    
        void main()
        {
            vec4 v = vec4(in_pos, 1.0);
            gl_Position = fullTransformMatrix* v;
    
            vec3 lightVector = normalize(lightPosition-normal);
            float brightness = dot(lightVector,normal);
            theColor = vertexColor * vec3( brightness, brightness, brightness);// * ambientLight;
    
            UV = vertexUV;
        }
    );
    
    const char* frag = GLSL
    (
        330 core,
        out vec4 color;
    
        in vec3 theColor;
        in vec2 UV;
    
        uniform sampler2D mySampler;
    
        void main()
        {
            color = texture(mySampler,UV);
        }
    );
    
    
    GLuint LoadTexture(const char * filename)
    {
        int width = 0, height = 0, n = 0;
        unsigned char* data = stbi_load
            (
            filename,
            &width,
            &height,
            &n,
            3
            );
    
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glActiveTexture(GL_TEXTURE0);
        GLuint texture;
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    
        stbi_image_free( data );
    
        return texture;
    }
    
    const float movementspeed = 0.01f;
    class Camera{
        vec3 position;
        vec3 viewDirection;
        const vec3 UP;
        vec2 oldmouseposition;
    public:
        Camera();
        mat4 getWorldToViewMatrix() const;
        void mouseUpdate(const vec2 &newMousePosition);
        void moveForward();
        void moveBackWard();
        void left();
        void right();
        void up();
        void down();
    
    };
    Camera::Camera() :viewDirection(0.0f, 0.0f, -1.0f), UP(0.0f, 1.0f, 0.0f){}
    void Camera::mouseUpdate(const vec2 &newMousePosition){
    
        glm::vec2 mouseDelta = newMousePosition - oldmouseposition;
        if (glm::length(mouseDelta) >10.0f)
        {
            oldmouseposition = newMousePosition;
            return;
        }
        viewDirection = glm::mat3(glm::rotate(-mouseDelta.x*0.5f, UP)) * viewDirection;
        oldmouseposition = newMousePosition;
    
    }
    void Camera::moveForward(){
        position -= movementspeed *viewDirection;
    }
    void Camera::moveBackWard(){
        position += movementspeed *viewDirection;
    }
    void Camera::left(){
        glm::vec3 strafeDirection = glm::cross(viewDirection, UP);
        position += movementspeed *strafeDirection;
    }
    void Camera::right(){
        glm::vec3 strafeDirection = glm::cross(viewDirection, UP);
        position += -movementspeed *strafeDirection;
    }
    void Camera::up(){
        position += movementspeed *UP;
    }
    void Camera::down(){
        position += -movementspeed *UP;
    }
    mat4 Camera::getWorldToViewMatrix() const {
        return lookAt(position, position - viewDirection, UP);
    }
    
    
    int main(int argc, char ** argv)
    {
        if (!glfwInit())
            exit(EXIT_FAILURE);
    
        GLFWwindow* window;
        window = glfwCreateWindow(640, 480, "My 3D World", NULL, NULL);
        if (!window)
        {
            glfwTerminate();
            exit(EXIT_FAILURE);
        }
        glfwMakeContextCurrent(window);
        glfwSwapInterval(1);
        glewExperimental = true;
        if (glewInit() != GLEW_OK){
            glfwTerminate();
            exit(EXIT_FAILURE);
        }
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
    
        GLuint program = Program::Load
            (
            vert, GL_VERTEX_SHADER,
            frag, GL_FRAGMENT_SHADER,
            NULL
            );
    
        struct Vertex{
            glm::vec3 position;
            glm::vec3 color;
            glm::vec2 texture;
            glm::vec3 normal;
        };
        Vertex verts[] = {
            vec3(-1.0f, +1.0f, +1.0f), // 0
            vec3(0.0f, 1.0f, 0.0f), // Colour
            vec2(0.0f, 0.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(+1.0f, +1.0f, +1.0f), // 1
            vec3(0.0f, 0.0f, 1.0f), // Colour
            vec2(1.0f, 0.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(+1.0f, +1.0f, -1.0f), // 2
            vec3(1.0f, 0.0f, 0.0f), // Colour
            vec2(1.0f, 1.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(-1.0f, +1.0f, -1.0f), // 3
            vec3(0.0f, 0.0f, 0.0f), // Colour
            vec2(0.0f, 1.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
    
            vec3(-1.0f, +1.0f, -1.0f), // 4
            vec3(0.0f, 1.0f, 0.0f), // Colour
            vec2(0.0f, 0.0f),
            vec3(0.0f, -1.0f, 0.0f), //normal
            vec3(+1.0f, +1.0f, -1.0f), // 5
            vec3(1.0f, 0.0f, 0.0f), // Colour
            vec2(1.0f, 0.0f),
            vec3(0.0f, -1.0f, 0.0f), //normal
            vec3(+1.0f, -1.0f, -1.0f), // 
            vec3(0.0f, 0.0f, 1.0f), // Colour
            vec2(1.0f, 1.0f),
            vec3(0.0f, -1.0f, 0.0f), //normal
            vec3(-1.0f, -1.0f, -1.0f), // 7
            vec3(0.0f, 1.0f, 0.0f), // Colour
            vec2(0.0f, 1.0f),
            vec3(0.0f, -1.0f, 0.0f), //normal
    
            vec3(+1.0f, +1.0f, -1.0f), // 8
            vec3(0.0f, 0.0f, 1.0f), // Colour
            vec2(0.0f, 0.0f),
            vec3(0.0f, 0.0f, -1.0f), //normal
            vec3(+1.0f, +1.0f, +1.0f), // 9
            vec3(0.0f, 1.0f, 0.0f), // Colour
            vec2(1.0f, 0.0f),
            vec3(0.0f, 0.0f, -1.0f), //normal
            vec3(+1.0f, -1.0f, +1.0f), // 10
            vec3(0.0f, 0.0f, 1.0f), // Colour
            vec2(1.0f, 1.0f),
            vec3(0.0f, 0.0f, -1.0f), //normal
            vec3(+1.0f, -1.0f, -1.0f), // 11
            vec3(0.0f, 0.0f, 1.0f), // Colour
            vec2(0.0f, 1.0f),
            vec3(0.0f, 0.0f, -1.0f), //normal
    
            vec3(-1.0f, +1.0f, +1.0f), // 12
            vec3(0.0f, 0.0f, 1.0f), // Colour
            vec2(0.0f, 0.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(-1.0f, +1.0f, -1.0f), // 13
            vec3(1.0f, 0.0f, 0.0f), // Colour
            vec2(1.0f, 0.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(-1.0f, -1.0f, -1.0f), // 14
            vec3(0.0f, 1.0f, 0.0f), // Colour
            vec2(1.0f, 1.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(-1.0f, -1.0f, +1.0f), // 15
            vec3(0.0f, 1.0f, 0.0f), // Colour
            vec2(0.0f, 1.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
    
            vec3(+1.0f, +1.0f, +1.0f), // 16
            vec3(0.0f, 0.0f, 1.0f), // Colour
            vec2(0.0f, 0.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(-1.0f, +1.0f, +1.0f), // 17
            vec3(1.0f, 0.0f, 1.0f), // Colour
            vec2(1.0f, 0.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(-1.0f, -1.0f, +1.0f), // 18
            vec3(0.0f, 1.0f, 0.0f), // Colour
            vec2(1.0f, 1.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(+1.0f, -1.0f, +1.0f), // 19
            vec3(1.0f, 0.0f, 1.0f), // Colour
            vec2(0.0f, 1.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
    
            vec3(+1.0f, -1.0f, -1.0f), // 20
            vec3(0.0f, 1.0f, 0.0f), // Colour
            vec2(0.0f, 0.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(-1.0f, -1.0f, -1.0f), // 21
            vec3(0.0f, 1.0f, 0.0f), // Colour
            vec2(1.0f, 0.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(-1.0f, -1.0f, +1.0f), // 22
            vec3(0.0f, 1.0f, 1.0f), // Colour
            vec2(1.0f, 1.0f),
            vec3(0.0f, 1.0f, 0.0f), //normal
            vec3(+1.0f, -1.0f, +1.0f), // 23
            vec3(1.0f, 1.0f, 0.0f), // Colour
            vec2(0.0f, 1.0f),
            vec3(0.0f, 1.0f, 0.0f) //normal
        };
        GLushort indices[] = {
            0, 1, 2, 0, 2, 3, // Top
            4, 5, 6, 4, 6, 7, // Front
            8, 9, 10, 8, 10, 11, // Right
            12, 13, 14, 12, 14, 15, // Left
            16, 17, 18, 16, 18, 19, // Back
            20, 22, 21, 20, 23, 22 // Bottom
        };
        ////////VAO niepotrzebne
        ////////VBO
        GLuint vboID;
        glGenBuffers(1, &vboID);
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_DYNAMIC_DRAW);
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        glEnableVertexAttribArray(2);
        glEnableVertexAttribArray(3);
        GLuint indexbuff;
        glGenBuffers(1, &indexbuff);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
        //////
    
        glActiveTexture(GL_TEXTURE0);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, LoadTexture("TADdR.png"));
    
        Camera camera;
    
        while (!glfwWindowShouldClose(window))
        {
            glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
        
            glUseProgram(program);
    
            double xpos, ypos;
            glfwGetCursorPos(window, &xpos, &ypos);
        
            if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){
                camera.moveForward();
            }
            if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){
                camera.moveBackWard();
            }
            if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){
                camera.left();
            }
            if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS){
                camera.right();
            }
            if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS){
                camera.up();
            }
            if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS){
                camera.down();
            }
            if (xpos > 0 && xpos < 640 && ypos>0 && ypos < 400){
                camera.mouseUpdate(vec2(float(xpos / 50), float(ypos / 50)));
                std::cout << "pos x: " << xpos << "pos y: " << ypos << std::endl;
            }
    
            // textures
            glUniform1i(glGetUniformLocation(program, "mySampler"), 0);
            //AMBIENT LIGHT
            GLint ambientlightlocation = glGetUniformLocation(program, "ambientLight");
            vec3 ambientLight(0.3f, 0.3f, 0.3f);
            glUniform3fv(ambientlightlocation, 1, &ambientLight[0]);
    
            //Light
            GLint lightlocation = glGetUniformLocation(program, "lightPosition");
            vec3 lightposition(1.0f, 1.0f, -3.75f);
            glUniform3fv(lightlocation, 1, &lightposition[0]);
    
    
            GLint fullTransformMatrixUniformLocation = glGetUniformLocation(program, "fullTransformMatrix");
            mat4 fullTransformMatrix;
            mat4 projectionMatrix = perspective( glm::radians( 90.0f ), (480.0f / 640.0f), 0.1f, 5.0f);
            mat4 worldToProjectionMatrix = projectionMatrix* camera.getWorldToViewMatrix();
    
            //CUBE 1 tak sie robi gdyby sie roznily
            glBindBuffer(GL_ARRAY_BUFFER, vboID);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (void*)0);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 3));
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 6));
            glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 9));
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);
    
            mat4 cube1WorldMatrix = translate(vec3(1.0f, 0.0f, -3.75f)) * rotate(0.0f, vec3(0.0f, 1.0f, 1.0f));
            fullTransformMatrix = worldToProjectionMatrix *cube1WorldMatrix;
            glUniformMatrix4fv(fullTransformMatrixUniformLocation, 1, GL_FALSE, &fullTransformMatrix[0][0]);
            glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
        
            // CUBE 2 gdyby byly rozne 
            glBindBuffer(GL_ARRAY_BUFFER, vboID);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (void*)0);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 3));
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 6));
            glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 9));
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);
    
            mat4 cube2WorldMatrix = translate(vec3(-3.0f, 0.0f, -3.75f)) * rotate(126.0f, vec3(1.0f, 0.0f, 0.0f));
            fullTransformMatrix = worldToProjectionMatrix *cube2WorldMatrix;
            glUniformMatrix4fv(fullTransformMatrixUniformLocation, 1, GL_FALSE, &fullTransformMatrix[0][0]);
            glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
    
    
            glfwSwapBuffers(window);
            glfwPollEvents();
    
        }
        glfwDestroyWindow(window);
        glfwTerminate();
        exit(EXIT_SUCCESS);
    }