Saturday, November 23, 2013

Index Buffer Object

GPU-рүү оройнуудын массивийг хуулж тавьж байгаад зурах үйлдэл хийх нь ганц ширхэг гурвалжин дүрсний хувьд хамгийн сайн шийдэл, гэвч бодил байдал дээр дүрснүүд маш олон оройнуудаас бүрддэг бөгөөд зарим тохиолдолд өөр өөр гурвалжинг дүрслэх мөртөө оройнууд нь давхцах тохиолдол бий. Давхцсан өгөгдөл тооцоолно гэдэг цаанаа нөөц л үрж байгаа хэрэг. Тиймээс давхцсан оройг хасаад index-ээр хандаж ашиглавал илүү бага санах ойг модел дүрслэхэд ашиглах боломжтой
IBO буюу Index Buffer Object нь эдгээр оройнуудын өгөгдлүүд дээр өөрийн гэсэн зурах дарааллаар дүрс зурах боломжийг олгоно.



Vertex Shader
#version 330

layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;

out vec4 ex_Color;

void main(void)
{
 gl_Position = in_Position;
 ex_Color = in_Color;
}


Fragment Shader
#version 330

in vec4 ex_Color;
out vec4 out_Color;

void main(void)
{
 out_Color = ex_Color;
}


код
#define GLEW_STATIC
#include "GL/glew.h"
#include <GLFW/glfw3.h>
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>

using namespace std;

GLuint loadShader(string filePath, GLenum shaderType) {
    GLuint shaderID = 0;
    string shaderString;
    ifstream sourceFile(filePath.c_str());
    if (sourceFile) {
        shaderString.assign(
                (istreambuf_iterator<char>(sourceFile)),
                (istreambuf_iterator<char>()));
        shaderID = glCreateShader(shaderType);
        const GLchar* shaderSource = shaderString.c_str();
        glShaderSource(shaderID, 1, (const GLchar**) &shaderSource, NULL);
        glCompileShader(shaderID);
        GLint shaderCompiled = GL_FALSE;
        glGetShaderiv(shaderID, GL_COMPILE_STATUS, &shaderCompiled);
        if (shaderCompiled != GL_TRUE) {
            cout << "cannot compiled" << endl;
            glDeleteShader(shaderID);
            shaderID = 0;
        }
        sourceFile.close();
    } else {
        cout << "cannot open file" << endl;
    }
    return shaderID;
}

int main(int argc, char** argv) {

    GLFWwindow* window;
    if (!glfwInit())
        return EXIT_FAILURE;

    window = glfwCreateWindow(800, 600, "OpenGL Index Buffer Object", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return EXIT_FAILURE;
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    glfwMakeContextCurrent(window);

    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        cout << "error in glewInit " << glewGetErrorString(err) << endl;
        return EXIT_FAILURE;
    }

    cout << "start cooking" << endl;

    GLuint programID = glCreateProgram();
    cout << "created program : " << programID << endl;
    GLuint vertexShader = loadShader("simple.vert.glsl", GL_VERTEX_SHADER);
    if (vertexShader == 0) {
        glDeleteProgram(programID);
        programID = 0;
        return EXIT_FAILURE;
    }
    glAttachShader(programID, vertexShader);
    GLuint fragmentShader = loadShader("simple.frag.glsl", GL_FRAGMENT_SHADER);
    if (fragmentShader == 0) {
        glDeleteProgram(programID);
        programID = 0;
        return EXIT_FAILURE;
    }
    glAttachShader(programID, fragmentShader);
    glLinkProgram(programID);
    glUseProgram(programID);
    GLint programSuccess = GL_TRUE;
    glGetProgramiv(programID, GL_LINK_STATUS, &programSuccess);
    if (programSuccess != GL_TRUE) {
        cout << "error in linkin program " << programID << endl;
        glDeleteProgram(programID);
        programID = 0;
        return EXIT_FAILURE;
    }


    GLuint VaoId, BufferId, IndexBufferId[2], ActiveIndexBuffer = 0;

    typedef struct {
        float XYZW[4];
        float RGBA[4];
    } Vertex;

    Vertex Vertices[] = {
        {
            { 0.0f, 0.0f, 0.0f, 1.0f},
            { 1.0f, 1.0f, 1.0f, 1.0f}
        }, // 0
        { // Дээд тал
            { -0.2f, 0.8f, 0.0f, 1.0f},
            { 0.0f, 1.0f, 0.0f, 1.0f}
        }, // 1
        {
            { 0.2f, 0.8f, 0.0f, 1.0f},
            { 0.0f, 0.0f, 1.0f, 1.0f}
        }, // 2
        {
            { 0.0f, 0.8f, 0.0f, 1.0f},
            { 0.0f, 1.0f, 1.0f, 1.0f}
        }, //3
        {
            { 0.0f, 1.0f, 0.0f, 1.0f},
            { 1.0f, 0.0f, 0.0f, 1.0f}
        }, // 4
        { // Доод тал
            { -0.2f, -0.8f, 0.0f, 1.0f},
            { 0.0f, 0.0f, 1.0f, 1.0f}
        }, // 5
        {
            { 0.2f, -0.8f, 0.0f, 1.0f},
            { 0.0f, 1.0f, 0.0f, 1.0f}
        }, // 6
        {
            { 0.0f, -0.8f, 0.0f, 1.0f},
            { 0.0f, 1.0f, 1.0f, 1.0f}
        }, //7
        {
            { 0.0f, -1.0f, 0.0f, 1.0f},
            { 1.0f, 0.0f, 0.0f, 1.0f}
        }, // 8
        { // Зүүн
            { -0.8f, -0.2f, 0.0f, 1.0f},
            { 0.0f, 1.0f, 0.0f, 1.0f}
        }, // 9
        {
            { -0.8f, 0.2f, 0.0f, 1.0f},
            { 0.0f, 0.0f, 1.0f, 1.0f}
        }, // 10
        {
            { -0.8f, 0.0f, 0.0f, 1.0f},
            { 0.0f, 1.0f, 1.0f, 1.0f}
        }, //11
        {
            { -1.0f, 0.0f, 0.0f, 1.0f},
            { 1.0f, 0.0f, 0.0f, 1.0f}
        }, // 12
        { // Баруун
            { 0.8f, -0.2f, 0.0f, 1.0f},
            { 0.0f, 0.0f, 1.0f, 1.0f}
        }, // 13
        {
            { 0.8f, 0.2f, 0.0f, 1.0f},
            { 0.0f, 1.0f, 0.0f, 1.0f}
        }, // 14
        {
            { 0.8f, 0.0f, 0.0f, 1.0f},
            { 0.0f, 1.0f, 1.0f, 1.0f}
        }, //15
        {
            { 1.0f, 0.0f, 0.0f, 1.0f},
            { 1.0f, 0.0f, 0.0f, 1.0f}
        } // 16
    };
    GLubyte Indices[] = {
        // Дээд
        0, 1, 3,
        0, 3, 2,
        3, 1, 4,
        3, 4, 2,
        // Доод
        0, 5, 7,
        0, 7, 6,
        7, 5, 8,
        7, 8, 6,
        // Зүүн
        0, 9, 11,
        0, 11, 10,
        11, 9, 12,
        11, 12, 10,
        // Баруун
        0, 13, 15,
        0, 15, 14,
        15, 13, 16,
        15, 16, 14
    };
    GLubyte AlternateIndices[] = {
        // Гадна дөрвөлжингийн хил:
        3, 4, 16,
        3, 15, 16,
        15, 16, 8,
        15, 7, 8,
        7, 8, 12,
        7, 11, 12,
        11, 12, 4,
        11, 3, 4,
        // Доторхи дөрвөлжин
        0, 11, 3,
        0, 3, 15,
        0, 15, 7,
        0, 7, 11
    };

    const size_t BufferSize = sizeof (Vertices);
    const size_t VertexSize = sizeof (Vertices[0]);
    const size_t RgbOffset = sizeof (Vertices[0].XYZW);

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

    glGenBuffers(1, &BufferId);
    glBindBuffer(GL_ARRAY_BUFFER, BufferId);
    glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*) RgbOffset);

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glGenBuffers(2, IndexBufferId);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof (Indices), Indices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof (AlternateIndices), AlternateIndices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[0]);


    float deltaTime = 0.0f;
    float startTime = glfwGetTime();
    float buffTime = 0.0;
    int counter = 0;
    while (!glfwWindowShouldClose(window)) {

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        if (ActiveIndexBuffer == 0) {
            glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_BYTE, NULL);
        } else {
            glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, NULL);
        }

        glfwSwapBuffers(window);
        glfwPollEvents();

        double lastTime = glfwGetTime();
        deltaTime = lastTime - startTime;
        startTime = lastTime;
        counter++;
        buffTime += deltaTime;
        if (buffTime > 1.0f) {
            buffTime = 0.0f;
            cout << "fps " << counter << endl;
            counter = 0;
        }
    }

    // VBO устгах
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glDeleteBuffers(1, &BufferId);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDeleteBuffers(2, IndexBufferId);

    glBindVertexArray(0);
    glDeleteVertexArrays(1, &VaoId);

    // shader ээ устгах
    glUseProgram(0);

    glDetachShader(programID, vertexShader);
    glDetachShader(programID, fragmentShader);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    glDeleteProgram(programID);

    glfwTerminate();
    return 0;
}


Коодын тайлбарыг завтай үедээ аажуу уужууханшиг тайлбарланаа. Одоогоор ингээд байж байг