为OpenGL多维数据集添加纹理?

时间:2015-06-25 01:15:29

标签: c opengl

使用VAO和VBO我已经提出了这个代码,它将一堆立方体渲染成一个巨大的块,所有这些都具有相同的设置颜色方案:

    #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;
    }

此代码有效,但效果很好,但我立即注意到它缺乏加载纹理的能力。所以我研究了如何加载和渲染纹理,但遗憾的是我无法让它工作。到目前为止,关于加载和渲染纹理的内容是:

    #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;
    }

我意识到,即使在我的工作代码中,也可能有许多其他我需要修复的东西,这是我仍在学习的预期。所以,我想知道是否有一种方法我仍然可以使用这些代码来处理纹理(也许我只是错过了一些小的东西?)或者我是否已经开始完全在这段代码中实现纹理(在这种情况下,我将如何处理它?)。

1 个答案:

答案 0 :(得分:1)

Haven未对您的代码进行测试,因此这可能会有所帮助或无法帮助。

1

我看到你的顶点缓冲区设置为

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

也就是说,你的glVertexAttripPointer调用必须是:

// 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));

这个功能对你没什么用。它会搞乱你的glVertexAttribPointer调用。带他们出去。

3

你的顶点着色器源shell是:

#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;
}

你的片段着色器:

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

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

4

如果您认为您的紫外线没有正确发送,您可以随时通过将紫外线渲染为红色/绿色进行测试。您将获得类似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;
    }

没有理由将纹理和着色器程序绑定为vao初始化的一部分。纹理绑定和程序都不是vao的一部分。 here

6

如果您不确定是否正确创建了纹理,请记住SOIL有一个简单的功能,可以为您完成所有工作。

/**
    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();
}

您在此处调用的每个Matrix函数都没有意义。

您的顶点着色器甚至无法使用任何推动的矩阵,因为您从未告诉它。你是ES版本。您无法从顶点着色器访问这些矩阵,如以下存根所述:

(从here归档)

  

一些框架(特别是OpenGL兼容性配置文件,但是   OpenGL核心配置文件和OpenGL ES 2.x都没有提供   内置制服来访问GLSL中的某些顶点变换   着色器。它们不应该被声明,但这里是声明   指定他们的类型:

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];

如果您使用的是现代OpenGL,那么您将完全按照this文章的说法进行操作。

8

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

这部分是正确的。为什么要注释掉?