[OpenGL]紋理貼圖實現 總結

實現步驟

第一步:設置所須要的OpenGL環境
設置上下文環境
刪除已經存在的渲染的緩存
設置顏色緩存
設置幀緩存
清除緩存
設置窗口大小
開啓功能
編譯shander
使用program
獲取shader中的屬性和uniform索引數組

第二步:繪製圖片
獲取圖片數據而且的到對應的紋理id
指定紋理,綁定紋理
開始對圖形進行渲染
(
啓用頂點屬性數組紋理座標,將紋理座標傳遞到shader中
啓用頂點屬性數組頂點座標,將頂點座標傳遞到shader中
啓用索引數組
開始繪製
)
解綁紋理xcode

實現

此次實現的過程有些艱難啊,走了不少的彎路,不過也所以學到蠻多的,本身寫的怎麼都運行不了,可是在別人的基礎上運行就不行,其中錯誤的地方有:1.紋理的數據錯誤,使用png的庫失敗;2.繪製函數的參數錯誤;3.使用新版本的glsl語言版本,可是xcode並不支持,並不熟悉期間的語言版本迭代;緩存

實現代碼:函數

主程序

#include "SOIL.h"

static void error_callback(int error, const char* description)
{
    fprintf(stderr, "Error: %s\n", description);
}

int main(void)
{
    GLFWwindow* window;
    
    glfwSetErrorCallback(error_callback);
    
    if (!glfwInit())
        exit(EXIT_FAILURE);
    
    window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
    if (!window)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glfwMakeContextCurrent(window);
    glewExperimental = GL_TRUE;
    glewInit();
    
    glfwSwapInterval(1);
    glViewport(0, 0, 640, 480);
    
    bool ret = getImageData("/Users/staff/Desktop/Moni/Moni/wall.png");
    if (!ret) {
        cout << "get iamge data is failed." << endl;
    }
    else {
        cout << "get iamge data is success." << endl;
        
        //測試圖片數據
        //        FILE * file;
        //        file = fopen("/Users/staff/Desktop/abc.png","wb");
        //        if (file)
        //        {
        //            fwrite(_sp_image_data.getBytes(),1,_sp_image_data.getSize(), file);
        //        }
        //        fclose(file);
    }
    
    // 第一行和第三行不是嚴格必須的,默認使用GL_TEXTURE0做爲當前激活的紋理單元
    
    /**
     *  GL_TEXTURE_2D表示操做2D紋理
     *  建立紋理對象,
     *  綁定紋理對象,
     */
    glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
    glGenTextures(1, &_sp_textureID);
    glBindTexture(GL_TEXTURE_2D, _sp_textureID);
    
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
//    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
//    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

    /**
     *  將圖像數據傳遞給到GL_TEXTURE_2D中, 因其於textureID紋理對象已經綁定,因此即傳遞給了textureID紋理對象中。
     *  glTexImage2d會將圖像數據從CPU內存經過PCIE上傳到GPU內存。
     *  不使用PBO時它是一個阻塞CPU的函數,數據量大會卡
     */
//    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _sp_image_size.getX(), _sp_image_size.getY(), 0, GL_RGBA, GL_UNSIGNED_BYTE, _sp_image_data.getBytes());
//    glGenerateMipmap(GL_TEXTURE_2D);
    
    int width, height;
    unsigned char* image = SOIL_load_image("/Users/staff/Desktop/fgh/fgh/wall.jpg", &width, &height, 0, SOIL_LOAD_RGB);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
    glGenerateMipmap(GL_TEXTURE_2D);
    SOIL_free_image_data(image);
    
    glBindTexture(GL_TEXTURE_2D, 0);
    
    _vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(_vertexShader, 1, &CCPositionTextureColorVert, NULL);
    glCompileShader(_vertexShader);
    
    GLint status;
    glGetShaderiv(_vertexShader, GL_COMPILE_STATUS, &status);
    if (!status) {
        GLint infoLen = 0;
        glGetShaderiv(_vertexShader, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen) {
            char* infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
            glGetShaderInfoLog(_vertexShader, infoLen, NULL, infoLog);
            cout << "compile vert shader wrong..." << infoLog << endl;
        }
    }
    else {
        cout << "compile vert shader success..." << endl;
    }
    
    _fragShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(_fragShader, 1, &CCPositionTextureColorFrag, NULL);
    glCompileShader(_fragShader);
    
    glGetShaderiv(_fragShader, GL_COMPILE_STATUS, &status);
    if (!status) {
        GLint infoLen = 0;
        glGetShaderiv(_fragShader, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen) {
            char* infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
            glGetShaderInfoLog(_fragShader, infoLen, NULL, infoLog);
            cout << "compile frag shader wrong..." << infoLog << endl;
        }
    }
    else {
        cout << "compile vert frag success..." << endl;
    }
    
    _program = glCreateProgram();
    glAttachShader(_program, _vertexShader);
    glAttachShader(_program, _fragShader);
    glLinkProgram(_program);
    
    glGetProgramiv(_program, GL_LINK_STATUS, &status);
    if (status == GL_FALSE) {
        GLint infoLen = 0;
        glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen) {
            char* infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
            glGetProgramInfoLog(_program, infoLen, NULL, infoLog);
            cout << "link program wrong..." << infoLog << endl;
        }
    }
    else {
        cout << "the program link success." << endl;
    }
    
    //設置頂點數據(和緩衝)和屬性指針
    GLfloat vertices[] = {
        // Positions          // Colors           // Texture Coords
        0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   2.0f, 0.1f,
        0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   2.0f, 0.8f,
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.5f, 0.8f,
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.5f, 0.1f
    };
    GLuint indices[] = {
        0, 1, 3,
        1, 2, 3
    };
    
    
    GLuint VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);
    
    glBindVertexArray(VAO);
    
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
    GLuint _positionSlot = glGetAttribLocation(_program, "position");
    GLuint _colorSlot = glGetAttribLocation(_program, "color");
    GLuint _textureCoordsSlot = glGetAttribLocation(_program, "texCoord");
    //GLuint _textureSlot = glGetUniformLocation(shader.program, "ourTexture");
    
    glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(_positionSlot);
    
    glVertexAttribPointer(_colorSlot, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(_colorSlot);
    
    glVertexAttribPointer(_textureCoordsSlot, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
    glEnableVertexAttribArray(_textureCoordsSlot);
    
    glBindVertexArray(0);
    
    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();
        int width, height;
        glfwGetFramebufferSize(window, &width, &height);
        glViewport(0, 0, width, height);
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        
        //use
        glUseProgram(_program);
        
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, _sp_textureID); // 綁定,便可從_textureID中取出圖像數據
        glUniform1i(glGetUniformLocation(_program, "ourTexture1"), 0);
        
        //draw
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);
        
        glfwPollEvents();
        glfwSwapBuffers(window);
    }
    
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    
    glfwDestroyWindow(window);
    
    glfwTerminate();
    exit(EXIT_SUCCESS);
}

上面是主程序的代碼,除了這個,還須要頂點shader和片元shader;其實這裏有個坑,就是glsl的語言版本,越望越後面,增長了更多的新 功能,致使我不認識,從而使用了新版本的,同時xcode只更新了到了2.0上,其餘版本在xcode並不能使用,所以導編編譯失敗。測試

先是頂點shader:

const char* CCPositionTextureColorVert = STRINGIFY(
attribute vec3 position;
attribute vec3 color;
attribute vec2 texCoord;
                                                   
varying vec3 ourColor;
varying vec2 TexCoord;
                                                   
void main() {
    gl_Position = vec4(position, 1.0);
    ourColor = color;
    TexCoord = texCoord;
}
);

接下來的是片元shader

const char* CCPositionTextureColorFrag = STRINGIFY(
varying vec3 ourColor;
varying vec2 TexCoord;
                                                   
//varying vec4 color;
                                                   
uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;
uniform float mixValue;
                                                   
void main() {
    gl_FragColor = mix(texture2D(ourTexture1, TexCoord) * vec4(ourColor, 1.0), texture2D(ourTexture2, vec2(-TexCoord.x, TexCoord.y)), mixValue);
}
);
相關文章
相關標籤/搜索