0
votes

Using VAOs and VBOs I've come up with this code that renders a bunch of cubes into one huge block, all with the same set color scheme:

    #include <math.h>
    #include <time.h>

    #include <stdio.h>
    #include <stdlib.h>

    #include <GL/glew.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <GL/glut.h>

    #define WIDTH 0x320
    #define HEIGHT 0x258

    #define GLUT_KEY_LSHIFT 112
    #define QUIT 0x11
    #define ESC  0x1B

    typedef char* string;

    typedef struct vertex {

        float x;
        float y;
        float z;
    } Vertex;

    float angle = 0.0;
    float deltaX, deltaY;
    float deltaS, deltaSt;
    float deltaUp;

    float vx, vz, vy;
    float x = 0.0f, y = 0.0f, z = 0.0f;

    float defaultSpeed = 1.0f;
    float speed = 1.0f;

    float lastMousePosY = HEIGHT / 2;
    float lastMousePosX = WIDTH / 2;

    int nFrames;
    double lastTime;

    GLint up, down;
    GLuint vbo0, vbo1, ibo, vao;
    GLint indexAmnt, vertexAmnt, colorAmnt;
    GLint menuId;
    GLenum mode;

    int release;

    int xBlocks = 30;
    int yBlocks = 4;
    int zBlocks = 16;

    void direction(float delta_h, float delta_v)
    {
        angle += delta_h;
        vx = sin(angle);
        vz = -cos(angle);
        vy += sin(delta_v) * cos(delta_v);
    }

    void position(float delta_x, float delta_z)
    {
        x += delta_z * vx * speed;
        z += delta_z * vz * speed;

        x += delta_x * -vz * speed;
        z += delta_x * vx * speed;
    }

    int toRGBA(int r, int g, int b, int a)
    {
        return ((a << 24) | (b << 16) | (g << 8) | r);
    }

    Vertex initVector(float x, float y, float z)
    {
        Vertex v = {.x=x, .y=y, .z=z};
        return v;
    }

    unsigned int initVertexBuffer(Vertex* v)
    {
        unsigned int vbo_v;

        glGenBuffers(1, &vbo_v);
        glBindBuffer(GL_ARRAY_BUFFER, vbo_v);
        glBufferData(GL_ARRAY_BUFFER, vertexAmnt * sizeof(Vertex), v, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        return vbo_v;
    }

    unsigned int initColorBuffer(int* c)
    {
        unsigned int vbo_c;

        glGenBuffers(1, &vbo_c);
        glBindBuffer(GL_ARRAY_BUFFER, vbo_c);
        glBufferData(GL_ARRAY_BUFFER, colorAmnt * sizeof(int), c, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        return vbo_c;
    }

    unsigned int initIndexBuffer(int *i)
    {
        unsigned int ibo_i;

        glGenBuffers(1, &ibo_i);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_i);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexAmnt * sizeof(int), i, GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

        return ibo_i;
    }

    void menuActions(int value)
    {
        switch(value)
        {
        case 1:
            mode = GL_LINES;
            break;
        case 0:
            mode = GL_TRIANGLES;
            break;
        default:
            break;
        }
    }

    int createMenu()
    {
        int menu;

        menu = glutCreateMenu(menuActions);
        glutAddMenuEntry("On", 1);
        glutAddMenuEntry("Off", 0);

        return menu;
    }

    unsigned int initVertexArray()
    {
        GLuint vao_a;

        glGenVertexArrays(1, &vao_a);
        glBindVertexArray(vao_a);

        glBindBuffer(GL_ARRAY_BUFFER, vbo1);
        glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(int), 0);
        glEnableClientState(GL_COLOR_ARRAY);

        glBindBuffer(GL_ARRAY_BUFFER, vbo0);
        glVertexPointer(3, GL_FLOAT, sizeof(Vertex), 0);
        glEnableClientState(GL_VERTEX_ARRAY);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

        glBindVertexArray(0);

        return vao_a;
    }

    void loadgame()
    {
        Vertex vertices[] = {

            initVector(-0.5f, -0.5f, 0.5f),
            initVector(0.5f, -0.5f, 0.5f),
            initVector(0.5f, 0.5f, 0.5f),
            initVector(-0.5f, 0.5f, 0.5f), 
            initVector(-0.5f, -0.5f, -0.5f), 
            initVector(0.5f, -0.5f, -0.5f),
            initVector(0.5f, 0.5f, -0.5f),
            initVector(-0.5f, 0.5f, -0.5f)
        };

        int colors[] = {

            toRGBA(0xff, 0x00, 0x00, 0xff),
            toRGBA(0xff, 0xa5, 0x00, 0xff),
            toRGBA(0xa5, 0x2a, 0x2a, 0xff),
            toRGBA(0x80, 0x00, 0x00, 0xff),
            toRGBA(0x00, 0x00, 0xff, 0xff),
            toRGBA(0x00, 0xff, 0xff, 0xff),
            toRGBA(0x00, 0x80, 0x00, 0xff),
            toRGBA(0xad, 0xff, 0x2f, 0xff)
        };

        int indices[] = {

            0, 1, 2, 2, 3, 0, 
            3, 2, 6, 6, 7, 3, 
            7, 6, 5, 5, 4, 7, 
            4, 0, 3, 3, 7, 4, 
            0, 1, 5, 5, 4, 0,
            1, 5, 6, 6, 2, 1
        };

        vertexAmnt = sizeof(vertices) / sizeof(Vertex);
        colorAmnt = sizeof(colors) / sizeof(int);
        indexAmnt = sizeof(indices) / sizeof(int);

        vbo0 = initVertexBuffer(vertices);
        vbo1 = initColorBuffer(colors);
        ibo = initIndexBuffer(indices);
        vao = initVertexArray();

        mode = GL_TRIANGLES;

        menuId = createMenu();
        glutAttachMenu(GLUT_RIGHT_BUTTON);
        glClearColor(0.6f, 0.6f, 1.0f, 1.0f);

        lastTime = time(NULL);
    }

    void input(int key, int ix, int iy)
    {
        if(key == GLUT_KEY_LSHIFT){ deltaUp = -0.3f; down = 1; }
    }

    void input_r(int key, int ix, int iy)
    {
        if(key == GLUT_KEY_LSHIFT) down = 0;
    }

    void keyboard(unsigned char key, int kx, int ky)
    {
        if(key == QUIT) exit(0);
        if(key == ESC) release = 1;
        if(key == 'w') deltaS = 0.5f;
        if(key == 's') deltaS = -0.5f;
        if(key == 'a') deltaSt = -0.5f;
        if(key == 'd') deltaSt = 0.5f;
        if(key == 'r') speed = defaultSpeed * 5.0;
        if(key == ' '){ deltaUp = 0.3f; up = 1; }
    }

    void keyboard_r(unsigned char key, int kx, int ky)
    {
        if(key == ESC) release = 0;
        if(key == 'w' || key == 's') deltaS = 0.0f;
        if(key == 'a' || key == 'd') deltaSt = 0.0f;
        if(key == ' ') up = 0;
        if(key == 'r') speed = defaultSpeed;
    }

    void resetPointer()
    {
        glutWarpPointer(WIDTH / 2.0, HEIGHT / 2.0);

        lastMousePosY = HEIGHT / 2.0;
        lastMousePosX = WIDTH / 2.0;
    }

    void mouse(int mx, int my)
    {
        if(!release)
        {
            if(fabs(WIDTH / 2 - mx) > 15 ||
                    fabs(HEIGHT / 2 - my) > 15)
                        resetPointer();
            else
            {
                int vMotion = lastMousePosY - my;
                int hMotion = lastMousePosX - mx;

                deltaX = -hMotion / 25.0;
                deltaY = vMotion / 25.0;

                lastMousePosY = my;
                lastMousePosX = mx;
            }
        }
    }

    void render()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        const double w = glutGet(GLUT_WINDOW_WIDTH);
        const double h = glutGet(GLUT_WINDOW_HEIGHT);

        gluPerspective(45.0, w / h, 0.1, 1000.0);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        gluLookAt(x, y, z, x + vx, y + vy,  z + vz, 0.0f, 1.0f,  0.0f);
        glRotatef(angle, 0.0, 1.0, 0.0);

        int i = 0, j = 0, k = 0;
        for(; i < yBlocks; i ++)
            for(j = -xBlocks / 2; j < xBlocks / 2; j ++)
                for(k = -zBlocks / 2; k < zBlocks / 2; k ++)
                {
                    glPushMatrix();
                    glTranslatef((float)j, -(float)i - 1.7f, (float)k);

                    glBindVertexArray(vao);
                    glDrawElements(mode, indexAmnt, GL_UNSIGNED_INT, NULL);
                    glBindVertexArray(0);

                    glPopMatrix();
                }
        glutSwapBuffers();
    }

    void update()
    {
        if(deltaX || deltaY)
            direction(deltaX, deltaY);
        if(deltaS || deltaSt)
            position(deltaSt, deltaS);

        deltaX *= 0.9f;
        deltaY *= 0.9f;

        if(up == 0 && down == 0)
            deltaUp *= 0.9;

        if(fabs(deltaUp) >= 0.001f)
            y += deltaUp;

        double currentTime = time(NULL);
        nFrames ++;

        if(currentTime - lastTime >= 1.0)
        {
            //printf("%f ms/frame\n", 1000.0 / (double)nFrames);
            printf("%d fps\n", nFrames);
            defaultSpeed = (float)nFrames / 60.0f;
            nFrames = 0;
            lastTime += 1.0;
        }
        glutPostRedisplay();
    }

    int main(int argc, string argv[])
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

        glutInitWindowSize(WIDTH, HEIGHT);
        glutCreateWindow("First Person World");

        glutDisplayFunc(render);
        glutIdleFunc(update);
        glutPassiveMotionFunc(mouse);
        glutKeyboardFunc(keyboard);
        glutKeyboardUpFunc(keyboard_r);
        glutSpecialFunc(input);
        glutSpecialUpFunc(input_r);
        glutSetCursor(GLUT_CURSOR_NONE);

        GLenum error = glewInit();

        if(error != GLEW_OK)
        {
            fprintf(stderr, "Error: %s\n", glewGetErrorString(error));
            return -1;
        }
        glewGetString(GLEW_VERSION);

        loadgame();

        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_CULL_FACE);
        glutMainLoop();

        return 0;
    }

This code works and it works well, but right away I notice it was lacking the ability to load textures. So I researched how to load and render textures, but sadly I have been unable to get it to work. What I have so far regarding loading and rendering textures is this:

    #include <math.h>
    #include <time.h>

    #include <stdio.h>
    #include <stdlib.h>

    #include <GL/glew.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <GL/glut.h>
    #include <SOIL/SOIL.h>

    #define WIDTH 0x320
    #define HEIGHT 0x258

    #define GLUT_KEY_LSHIFT 112
    #define QUIT 0x11
    #define ESC  0x1B

    typedef char* string;

    typedef struct vertex {

        float x;
        float y;
        float z;
        float u;
        float v;
    } Vertex;

    float angle = 0.0;
    float deltaX, deltaY;
    float deltaS, deltaSt;
    float deltaUp;

    float vx, vz, vy;
    float x = 0.0f, y = 0.0f, z = 0.0f;

    float defaultSpeed = 1.0f;
    float speed = 1.0f;

    float lastMousePosY = HEIGHT / 2;
    float lastMousePosX = WIDTH / 2;

    int nFrames;
    double lastTime;

    GLint up, down;
    GLuint vbo0, vbo1, ibo, vao, texId, progId;
    GLint indexAmnt, vertexAmnt, colorAmnt;
    GLint menuId;
    GLenum mode;

    int release;

    int xBlocks = 30;
    int yBlocks = 4;
    int zBlocks = 16;

    void direction(float delta_h, float delta_v)
    {
        angle += delta_h;
        vx = sin(angle);
        vz = -cos(angle);
        vy += sin(delta_v) * cos(delta_v);
    }

    void position(float delta_x, float delta_z)
    {
        x += delta_z * vx * speed;
        z += delta_z * vz * speed;

        x += delta_x * -vz * speed;
        z += delta_x * vx * speed;
    }

    Vertex initVertex(float x, float y, float z, float u, float v)
    {
        Vertex v0 = {.x=x, .y=y, .z=z, .u=u, .v=v};
        return v0;
    }

    unsigned int initShaderProgram()
    {
        unsigned int id_p, vs, fs;

        const char* vertShader =
        "#version 300 es\n"
        "in vec2 texcoord;"
        "out vec2 TexCoord;"
        "void main() {"
        "   TexCoord = texcoord;"
        "}";

        const char* fragShader =
        "#version 300 es\n"
        "uniform sampler2D cubeTex;"
        "in vec2 TexCoord;"
        "void main() {"
        "   gl_FragColor = texture(cubeTex, TexCoord);"
        "}";

        int compile_ok = 0;

        vs = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vs, 1, &vertShader, NULL);
        glCompileShader(vs);
        glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_ok);

        if(compile_ok == 0)
        {
            GLsizei slen = 0;
            GLint blen = 0;
            glGetShaderiv(vs, GL_INFO_LOG_LENGTH , &blen);
            fprintf(stderr, "Error in vertex shader:\n");
            GLchar* compiler_log = (GLchar*)malloc(blen);
            glGetShaderInfoLog(vs, blen, &slen, compiler_log);
            fprintf(stderr, "%s\n", compiler_log);
            free (compiler_log);
        }

        fs = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fs, 1, &fragShader, NULL);
        glCompileShader(fs);
        glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_ok);

        if(compile_ok == 0)
        {
            GLsizei slen = 0;
            GLint blen = 0;
            glGetShaderiv(fs, GL_INFO_LOG_LENGTH , &blen);
            fprintf(stderr, "Error in fragment shader:\n");
            GLchar* compiler_log = (GLchar*)malloc(blen);
            glGetShaderInfoLog(fs, blen, &slen, compiler_log);
            fprintf(stderr, "%s\n", compiler_log);
            free (compiler_log);
        }

        id_p = glCreateProgram();
        glAttachShader(id_p, vs);
        glAttachShader(id_p, fs);
        glLinkProgram(id_p);

        return id_p;
    }

    unsigned int initVertexBuffer(Vertex* v)
    {
        unsigned int vbo_v;

        glGenBuffers(1, &vbo_v);
        glBindBuffer(GL_ARRAY_BUFFER, vbo_v);
        glBufferData(GL_ARRAY_BUFFER, vertexAmnt * sizeof(Vertex), v, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        return vbo_v;
    }

    unsigned int initColorBuffer(int* c)
    {
        unsigned int vbo_c;

        glGenBuffers(1, &vbo_c);
        glBindBuffer(GL_ARRAY_BUFFER, vbo_c);
        glBufferData(GL_ARRAY_BUFFER, colorAmnt * sizeof(int), c, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        return vbo_c;
    }

    unsigned int initIndexBuffer(int *i)
    {
        unsigned int ibo_i;

        glGenBuffers(1, &ibo_i);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_i);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexAmnt * sizeof(int), i, GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

        return ibo_i;
    }

    unsigned int initTexture(const char* filename)
    {
        unsigned int id_t;

        glGenTextures(1, &id_t);

        int w, h;
        unsigned char* image = SOIL_load_image(filename, &w, &h, 0, SOIL_LOAD_RGB);

        glBindTexture(GL_TEXTURE_2D, id_t);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
        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_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        glBindTexture(GL_TEXTURE_2D, 0);
        SOIL_free_image_data(image);

        return id_t;
    }

    void menuActions(int value)
    {
        switch(value)
        {
        case 1:
            mode = GL_LINES;
            break;
        case 0:
            mode = GL_TRIANGLES;
            break;
        default:
            break;
        }
    }

    int createMenu()
    {
        int menu;

        menu = glutCreateMenu(menuActions);
        glutAddMenuEntry("On", 1);
        glutAddMenuEntry("Off", 0);

        return menu;
    }

    unsigned int initVertexArray()
    {
        GLuint vao_a;

        glGenVertexArrays(1, &vao_a);
        glBindVertexArray(vao_a);

        glBindBuffer(GL_ARRAY_BUFFER, vbo0);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)offsetof(Vertex, x));
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)offsetof(Vertex, u));
        glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (GLvoid*)offsetof(Vertex, x));
        glEnableClientState(GL_VERTEX_ARRAY);

        glActiveTexture(GL_TEXTURE0);
        glUniform1i(glGetUniformLocation(progId, "cubeTex"), 0);
        glVertexPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid*)offsetof(Vertex, u));
        glBindTexture(GL_TEXTURE_2D, texId);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
        glBindVertexArray(0);

        return vao_a;
    }

    void loadgame()
    {
        Vertex vertices[] = {

                initVertex(-0.5f, -0.5f, 0.5f, 0.0f, 0.0f),
                initVertex(0.5f, -0.5f, 0.5f, 1.0f, 0.0f),
                initVertex(0.5f, 0.5f, 0.5f, 1.0f, 1.0f),
                initVertex(-0.5f, 0.5f, 0.5f, 0.0f, 1.0f),
                initVertex(-0.5f, -0.5f, -0.5f, 0.0f, 0.0f),
                initVertex(0.5f, -0.5f, -0.5f, 1.0f, 0.0f),
                initVertex(0.5f, 0.5f, -0.5f, 1.0f, 1.0f),
                initVertex(-0.5f, 0.5f, -0.5f, 0.0f, 1.0f)
        };

        int indices[] = {

            0, 1, 2, 2, 3, 0,
            3, 2, 6, 6, 7, 3,
            7, 6, 5, 5, 4, 7,
            4, 0, 3, 3, 7, 4,
            0, 1, 5, 5, 4, 0,
            1, 5, 6, 6, 2, 1
        };

        vertexAmnt = sizeof(vertices) / sizeof(Vertex);
        indexAmnt = sizeof(indices) / sizeof(int);

        vbo0 = initVertexBuffer(vertices);
        ibo = initIndexBuffer(indices);
        texId = initTexture("stone.png");
        progId = initShaderProgram();
        vao = initVertexArray();

        mode = GL_TRIANGLES;

        menuId = createMenu();
        glutAttachMenu(GLUT_RIGHT_BUTTON);
        glClearColor(0.6f, 0.6f, 1.0f, 1.0f);

        lastTime = time(NULL);
    }

    void input(int key, int ix, int iy)
    {
        if(key == GLUT_KEY_LSHIFT){ deltaUp = -0.3f; down = 1; }
    }

    void input_r(int key, int ix, int iy)
    {
        if(key == GLUT_KEY_LSHIFT) down = 0;
    }

    void keyboard(unsigned char key, int kx, int ky)
    {
        if(key == QUIT) exit(0);
        if(key == ESC) release = 1;
        if(key == 'w') deltaS = 0.5f;
        if(key == 's') deltaS = -0.5f;
        if(key == 'a') deltaSt = -0.5f;
        if(key == 'd') deltaSt = 0.5f;
        if(key == 'r') speed = defaultSpeed * 5.0;
        if(key == ' '){ deltaUp = 0.3f; up = 1; }
    }

    void keyboard_r(unsigned char key, int kx, int ky)
    {
        if(key == ESC) release = 0;
        if(key == 'w' || key == 's') deltaS = 0.0f;
        if(key == 'a' || key == 'd') deltaSt = 0.0f;
        if(key == ' ') up = 0;
        if(key == 'r') speed = defaultSpeed;
    }

    void resetPointer()
    {
        glutWarpPointer(WIDTH / 2.0, HEIGHT / 2.0);

        lastMousePosY = HEIGHT / 2.0;
        lastMousePosX = WIDTH / 2.0;
    }

    void mouse(int mx, int my)
    {
        if(!release)
        {
            if(fabs(WIDTH / 2 - mx) > 15 ||
                    fabs(HEIGHT / 2 - my) > 15)
                        resetPointer();
            else
            {
                int vMotion = lastMousePosY - my;
                int hMotion = lastMousePosX - mx;

                deltaX = -hMotion / 25.0;
                deltaY = vMotion / 25.0;

                lastMousePosY = my;
                lastMousePosX = mx;
            }
        }
    }

    void render()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        const double w = glutGet(GLUT_WINDOW_WIDTH);
        const double h = glutGet(GLUT_WINDOW_HEIGHT);

        gluPerspective(45.0, w / h, 0.1, 1000.0);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        gluLookAt(x, y, z, x + vx, y + vy,  z + vz, 0.0f, 1.0f,  0.0f);
        glRotatef(angle, 0.0, 1.0, 0.0);

        glUseProgram(progId);

        int i = 0, j = 0, k = 0;
        for(; i < yBlocks; i ++)
            for(j = -xBlocks / 2; j < xBlocks / 2; j ++)
                for(k = -zBlocks / 2; k < zBlocks / 2; k ++)
                {
                    glPushMatrix();
                    glTranslatef((float)j, -(float)i - 1.7f, (float)k);

                    glBindVertexArray(vao);
                    //glActiveTexture(GL_TEXTURE0);
                    //glUniform1i(glGetUniformLocation(progId, "cubeTex"), 0);
                    //glBindTexture(GL_TEXTURE_2D, texId);
                    glDrawElements(mode, indexAmnt, GL_UNSIGNED_INT, NULL);
                    glBindVertexArray(0);

                    glPopMatrix();
                }
        glutSwapBuffers();
    }

    void update()
    {
        if(deltaX || deltaY)
            direction(deltaX, deltaY);
        if(deltaS || deltaSt)
            position(deltaSt, deltaS);

        deltaX *= 0.9f;
        deltaY *= 0.9f;

        if(up == 0 && down == 0)
            deltaUp *= 0.9;

        if(fabs(deltaUp) >= 0.001f)
            y += deltaUp;

        double currentTime = time(NULL);
        nFrames ++;

        if(currentTime - lastTime >= 1.0)
        {
            printf("%d fps\n", nFrames);
            defaultSpeed = (float)nFrames / 60.0f;
            nFrames = 0;
            lastTime += 1.0;
        }
        glutPostRedisplay();
    }

    int main(int argc, string argv[])
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

        glutInitWindowSize(WIDTH, HEIGHT);
        glutCreateWindow("First Person World");

        glutDisplayFunc(render);
        glutIdleFunc(update);
        glutPassiveMotionFunc(mouse);
        glutKeyboardFunc(keyboard);
        glutKeyboardUpFunc(keyboard_r);
        glutSpecialFunc(input);
        glutSpecialUpFunc(input_r);
        glutSetCursor(GLUT_CURSOR_NONE);

        GLenum error = glewInit();

        if(error != GLEW_OK)
        {
            fprintf(stderr, "Error: %s\n", glewGetErrorString(error));
            return -1;
        }
        glewGetString(GLEW_VERSION);

        loadgame();

        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_CULL_FACE);
        glutMainLoop();

        return 0;
    }

I realize that there may very well be many other things I need to fix, even within my working code, which is to be expected as I am still learning. So, I'd like to know if there's a way I can still get this code to work with textures (maybe I'm just missing something small?) or if I've been going about implementing textures in this code entirely (in which case, how would I go about it?).

1
That's much too much code for anyone to read. Please reduce it to the essential parts. What is the result of your current version?Nico Schertler

1 Answers

1
votes

Haven't tested your code, so this might help or not help.

1.

I see that your vertex buffer is setup such that

{ vertex0[x, y, z, u, v], vertex1[x, y, z, u, v] ... }

That is, your glVertexAttripPointer call must be:

// Okay. vbo0 will be used for later operations.
glBindBuffer(GL_ARRAY_BUFFER, vbo0);
// Okay. We will use attribute at 0.
glEnableVertexAttribArray(0);
// Okay. Vertex position attribute will be sent to attribute at 0.
glVertexAttribPointer( 0 // attribute at 0
                     , 3 , GL_FLOAT // 3 floating numbers for each vertex
                     , GL_FALSE // shell not normalize.
                     , 5 * sizeof(GLfloat) // jump 5 floating numbers to reach next vertex position
                     , (GLvoid*)0); // start from beginning
glEnableVertexAttribArray(1);
glVertexAttribPointer(1
                     , 2, GL_FLOAT
                     , GL_FALSE
                     , 5 * sizeof(GLfloat)
                     , (GLvoid*)offsetof(Vertex, u)); // start from fourth floating point number in buffer.

2.

//glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (GLvoid*)offsetof(Vertex, x));

this function is no more useful to you. It will just mess with your glVertexAttribPointer calls. take them out.

3.

And Your vertex shader source shell be:

#version 300 es
layout(location=0) in vec3 a_vertexPosition; // attribute at 0 is vertex position
layout(location=1) in vec2 a_TexCoord; // attribute at 1 is uv

out vec2 v_TexCoord;
void main() {
   gl_Position = vec4(a_vertexPosition, 1);
   v_TexCoord = a_TexCoord;
}

And your fragment shader:

#version 300 es
in vec2 v_TexCoord;
uniform sampler2D u_cubeTexture;

void main()
{
    gl_FragColor = texture(u_cubeTexture, v_TexCoord);
}

4.

If you don't think your uv is sent correctly, you can always test by rendering your uv as red/green color. You will get something like this.

void main()
{
    gl_FragColor = vec4(v_TexCoord.x, v_TexCoord.y, 0, 1);
}

5.

unsigned int initVertexArray()
    {
        GLuint vao_a;

        ...

        glActiveTexture(GL_TEXTURE0); // can be moved to different place
        glUniform1i(glGetUniformLocation(progId, "cubeTex"), 0); // Meaningless. You don't know what program is currently used.
        glVertexPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid*)offsetof(Vertex, u)); // Bad. Messes up your glVertexAttribPoionter call
        glBindTexture(GL_TEXTURE_2D, texId); // can be moved to different place

        ...

        return vao_a;
    }

There is no reason for binding of texture and shader program to be part of vao initialization. Neither texture binding and program is part of vao. here.

6.

If you are not sure if you created Texture correctly, remember that SOIL has a easy function that does all the job for you.

/**
    Loads an image from disk into an OpenGL texture.
    \param filename the name of the file to upload as a texture
    \param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
    \param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
    \param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
    \return 0-failed, otherwise returns the OpenGL texture handle
**/
unsigned int
    SOIL_load_OGL_texture
    (
        const char *filename,
        int force_channels,
        unsigned int reuse_texture_ID,
        unsigned int flags
    );

7.

void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    const double w = glutGet(GLUT_WINDOW_WIDTH);
    const double h = glutGet(GLUT_WINDOW_HEIGHT);

    gluPerspective(45.0, w / h, 0.1, 1000.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    gluLookAt(x, y, z, x + vx, y + vy,  z + vz, 0.0f, 1.0f,  0.0f);
    glRotatef(angle, 0.0, 1.0, 0.0);

    glUseProgram(progId);

    int i = 0, j = 0, k = 0;
    for(; i < yBlocks; i ++)
        for(j = -xBlocks / 2; j < xBlocks / 2; j ++)
            for(k = -zBlocks / 2; k < zBlocks / 2; k ++)
            {
                glPushMatrix();
                glTranslatef((float)j, -(float)i - 1.7f, (float)k);

                glBindVertexArray(vao);
                //glActiveTexture(GL_TEXTURE0);
                //glUniform1i(glGetUniformLocation(progId, "cubeTex"), 0);
                //glBindTexture(GL_TEXTURE_2D, texId);
                glDrawElements(mode, indexAmnt, GL_UNSIGNED_INT, NULL);
                glBindVertexArray(0);

                glPopMatrix();
            }
    glutSwapBuffers();
}

Every Matrix function you are calling here are meaningless.

Your vertex shader won't even use any of those matrices pushed, as you never told it to. You are on ES version. You cannot access those matrix from vertex shader as described by following stub:

(archived from here)

Some frameworks (in particular the OpenGL compatibility profile but neither the OpenGL core profile nor OpenGL ES 2.x) provide several built-in uniforms to access certain vertex transformations in GLSL shaders. They should not be declared, but here are the declarations to specify their types:

uniform mat4 gl_ModelViewMatrix;
uniform mat4 gl_ProjectionMatrix;
uniform mat4 gl_ModelViewProjectionMatrix;
uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];
uniform mat3 gl_NormalMatrix; // transpose of the inverse of the
   // upper left 3x3 matrix of gl_ModelViewMatrix
uniform mat4 gl_ModelViewMatrixInverse;
uniform mat4 gl_ProjectionMatrixInverse;
uniform mat4 gl_ModelViewProjectionMatrixInverse;
uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];
uniform mat4 gl_ModelViewMatrixTranspose;
uniform mat4 gl_ProjectionMatrixTranspose;
uniform mat4 gl_ModelViewProjectionMatrixTranspose;
uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];
uniform mat4 gl_ModelViewMatrixInverseTranspose;
uniform mat4 gl_ProjectionMatrixInverseTranspose;
uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;
uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];

If you are going with modern OpenGL, you will do exactly as this article is telling you.

8.

//glActiveTexture(GL_TEXTURE0);
//glUniform1i(glGetUniformLocation(progId, "cubeTex"), 0);
//glBindTexture(GL_TEXTURE_2D, texId);

this part was correct. Why is it commented out?