UV mapping wrong texture

by Bl4ckb0ne   Last Updated March 26, 2017 22:13 PM

I'm working on an instanced tile map system, and I have some problems to apply the tile texture to each tiles.

It seems that the texture applied to my tile is only 1px of the tile texture.

I tried severals calculations for the UVs but nothing conclusive.

Here's an output of what I have on the screen, and the code for my example

Output : enter image description here

#include <memory>
#include <cstring>

#include <boost/filesystem.hpp>
#include <boost/multi_array.hpp>
#define GLEW_STATIC
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <SDL2/SDL.h>

#include <pck/global.hpp>
#include <pck/program.hpp>
#include <pck/utils/stb_image.h>
#include <pck/window.hpp>

namespace fs = boost::filesystem;

const int WIDTH = 800, HEIGHT = 600;

GLuint map[3][8] = {
    { 1,  2,  3,  4,  5,  6,  7,  8},
    { 9, 10, 11, 12, 13, 14, 15, 16},
    {17, 18, 19, 20, 21, 22, 23, 24}
};


int main()
{
    // Wrapper around SDL2 window, also initializing OpenGL
    pck::Global::window.reset(new pck::Window("Test_gl", WIDTH, HEIGHT));

    // Vertices buffer
    GLfloat vertices[] = {
        0.0f, 1.0f,
        1.0f, 0.0f,
        0.0f, 0.0f,

        0.0f, 1.0f,
        1.0f, 0.0f,   
        1.0f, 1.0f                  
    }; 

    // Positions buffer 
    glm::vec2 positions[24];

    int index = 0;
    for(size_t j = 0; j < 3; ++j)
    {
        for(size_t i = 0; i < 8; ++i)
        {
            positions[index++] = glm::vec2(i, j);
        }
    }

    // Tileset caracteristics
    glm::vec2 tile_size(16.0f, 16.0f);
    glm::vec2 tex_size(128.0f, 208.0f);
    glm::vec2 tex_tile_size(8.0f, 13.0f); 

    // Textures coords buffer;

    // 24 tiles * 12 uvs 
    GLfloat tex_coords[24 * 12];

    index = 0;
    for(size_t j = 0; j < 3; ++j)
    {
        for(size_t i = 0; i < 8; ++i)
        {
            glm::vec2 uv(i / tile_size.x, j / tile_size.y);

            glm::vec2 ul(uv.x              , uv.y);
            glm::vec2 ur(uv.x + 1.0f / 8.0f, uv.y);
            glm::vec2 dl(uv.x + 1.0f / 8.0f, uv.y + 1.0f / 13.0f);
            glm::vec2 dr(uv.x              , uv.y + 1.0f / 13.0f);

            GLfloat uvs[] = {
                ul.x, ul.y,
                dl.x, dl.y,
                ur.x, ur.y,

                dr.x, dr.y,
                ur.x, ur.y,
                dl.x, dl.y          
            }; 

            // Fill the tex coords buffer
            std::memcpy(&tex_coords[index * 12], &uvs[0], sizeof(GLfloat) * 12);
            index++;
        }
    }

    // Texture declaration
    GLuint tex_ID;
    glGenTextures(1, &tex_ID);

    int w(0), h(0), c(0);
    unsigned char* data = stbi_load("tileset.png", &w, &h, &c, STBI_rgb_alpha);

    if(data == nullptr)
    {
        std::cout << "Failed to load texture\n";
        stbi_image_free(data);
        return 1;
    }

    glBindTexture(GL_TEXTURE_2D, tex_ID);
        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_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);

        if(c == 3)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        else if(c == 4)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

        glGenerateMipmap(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);

    stbi_image_free(data);

    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

        GLuint vertex_VBO;
        glGenBuffers(1, &vertex_VBO);

        glBindBuffer(GL_ARRAY_BUFFER, vertex_VBO);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
            glEnableVertexAttribArray(0);
            glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glVertexAttribDivisor(0, 0);

        // Also set instance data
        GLuint positions_VBO;
        glGenBuffers(1, &positions_VBO);

        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, positions_VBO);
            glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * 24, &positions[0], GL_STATIC_DRAW);
            glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);   
        glVertexAttribDivisor(1, 1);

        GLuint textures_VBO;
        glGenBuffers(1, &textures_VBO);

        glEnableVertexAttribArray(2);
        glBindBuffer(GL_ARRAY_BUFFER, textures_VBO);
            glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 24 * 12, &tex_coords[0], GL_STATIC_DRAW);
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);   
        glVertexAttribDivisor(2, 1);

    glBindVertexArray(0); 

    pck::Global::zoom = 2; 
    glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(pck::Global::width / pck::Global::zoom), 
        static_cast<GLfloat>(pck::Global::height / pck::Global::zoom), 0.0f, -1.0f, 1.0f);

    glm::mat4 model;
        model = glm::rotate(model, 0.0f, glm::vec3(0.0f, 0.0f, 1.0f)); 
        model = glm::scale(model, glm::vec3(16.0f, 16.0f, 1.0f)); 

    // Shader for instanciated tiles
    pck::VertShader vs(std::string(R"(
        #version 330 core
        layout (location = 0) in vec2 position;
        layout (location = 1) in vec2 offset;
        layout (location = 2) in vec2 texture;

        uniform mat4 model;
        uniform mat4 projection;

        out vec2 vs_tex_coords;

        void main()
        {
            gl_Position = projection * model * vec4(position + offset, 0.0f, 1.0f);
            vs_tex_coords = texture;
        }  
    )"));

    pck::FragShader fs(std::string(R"(
        #version 330 core

        in vec2 vs_tex_coords;

        out vec4 fs_color;

        uniform sampler2D image;

        void main()
        {
            fs_color = texture(image, vs_tex_coords);
        }
    )"));

    std::shared_ptr<pck::Program> program(new pck::Program(vs, fs));   

    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    while(pck::Global::window->is_closed())
    {
        while(pck::Global::window->poll_event() != 0)
        {
            if(pck::Global::event->type == SDL_QUIT)
            {
                pck::Global::window->close();
            }
            else if(pck::Global::event->type == SDL_KEYDOWN)
            {
                if(pck::Global::event->key.keysym.sym == SDLK_ESCAPE)
                    pck::Global::window->close();
            }
        }

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glBindTexture(GL_TEXTURE_2D, tex_ID);

        program->use();

        glUniformMatrix4fv(glGetUniformLocation(program->ID(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
        glUniformMatrix4fv(glGetUniformLocation(program->ID(), "model"), 1, GL_FALSE, glm::value_ptr(model)); 

        glBindVertexArray(VAO);
            glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 24);
        glBindVertexArray(0);

        pck::Global::window->update();
    }

    return 0;
}


Related Questions


Wrong UV calculation

Updated April 05, 2017 03:13 AM

Tile Map on a Mesh - Unity

Updated July 20, 2015 16:05 PM

Adventure Games - When and how to start mapping?

Updated June 30, 2015 13:05 PM

Tiled - move all tiles

Updated July 02, 2015 13:05 PM