首页 > 代码库 > OpenGL学习--07--模型加载(obj)

OpenGL学习--07--模型加载(obj)

 

1.tutorial07.cpp

// Include standard headers#include <stdio.h>#include <stdlib.h>#include <vector>// Include GLEW#include <GL/glew.h>// Include GLFW#include <glfw3.h>GLFWwindow* window;// Include GLM#include <glm/glm.hpp>#include <glm/gtc/matrix_transform.hpp>using namespace glm;#include <common/shader.hpp>#include <common/texture.hpp>#include <common/controls.hpp>#include <common/objloader.hpp>int main( void ){    // Initialise GLFW    if( !glfwInit() )    {        fprintf( stderr, "Failed to initialize GLFW\n" );        getchar();        return -1;    }    glfwWindowHint(GLFW_SAMPLES, 4);    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);    // Open a window and create its OpenGL context    window = glfwCreateWindow( 1024, 768, "Tutorial 07 - Model Loading", NULL, NULL);    if( window == NULL ){        fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );        getchar();        glfwTerminate();        return -1;    }    glfwMakeContextCurrent(window);    // Initialize GLEW    glewExperimental = true; // Needed for core profile    if (glewInit() != GLEW_OK) {        fprintf(stderr, "Failed to initialize GLEW\n");        getchar();        glfwTerminate();        return -1;    }    // Ensure we can capture the escape key being pressed below    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);    // Hide the mouse and enable unlimited mouvement    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);        // Set the mouse at the center of the screen    glfwPollEvents();    glfwSetCursorPos(window, 1024/2, 768/2);    // Dark blue background    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);    // Enable depth test    glEnable(GL_DEPTH_TEST);    // Accept fragment if it closer to the camera than the former one    glDepthFunc(GL_LESS);     // Cull triangles which normal is not towards the camera    glEnable(GL_CULL_FACE);    GLuint VertexArrayID;    glGenVertexArrays(1, &VertexArrayID);    glBindVertexArray(VertexArrayID);    // Create and compile our GLSL program from the shaders    GLuint programID = LoadShaders( "TransformVertexShader.vertexshader", "TextureFragmentShader.fragmentshader" );    // Get a handle for our "MVP" uniform    GLuint MatrixID = glGetUniformLocation(programID, "MVP");    // Load the texture    GLuint Texture = loadDDS("uvmap.DDS");        // Get a handle for our "myTextureSampler" uniform    GLuint TextureID  = glGetUniformLocation(programID, "myTextureSampler");    // Read our .obj file    std::vector<glm::vec3> vertices;    std::vector<glm::vec2> uvs;    std::vector<glm::vec3> normals; // Won‘t be used at the moment.    bool res = loadOBJ("cube.obj", vertices, uvs, normals);    // Load it into a VBO    GLuint vertexbuffer;    glGenBuffers(1, &vertexbuffer);    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);    GLuint uvbuffer;    glGenBuffers(1, &uvbuffer);    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);    glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);    do{        // Clear the screen        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);        // Use our shader        glUseProgram(programID);        // Compute the MVP matrix from keyboard and mouse input        computeMatricesFromInputs();        glm::mat4 ProjectionMatrix = getProjectionMatrix();        glm::mat4 ViewMatrix = getViewMatrix();        glm::mat4 ModelMatrix = glm::mat4(1.0);        glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;        // Send our transformation to the currently bound shader,         // in the "MVP" uniform        glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);        // Bind our texture in Texture Unit 0        glActiveTexture(GL_TEXTURE0);        glBindTexture(GL_TEXTURE_2D, Texture);        // Set our "myTextureSampler" sampler to user Texture Unit 0        glUniform1i(TextureID, 0);        // 1rst attribute buffer : vertices        glEnableVertexAttribArray(0);        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);        glVertexAttribPointer(            0,                  // attribute            3,                  // size            GL_FLOAT,           // type            GL_FALSE,           // normalized?            0,                  // stride            (void*)0            // array buffer offset        );        // 2nd attribute buffer : UVs        glEnableVertexAttribArray(1);        glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);        glVertexAttribPointer(            1,                                // attribute            2,                                // size            GL_FLOAT,                         // type            GL_FALSE,                         // normalized?            0,                                // stride            (void*)0                          // array buffer offset        );        // Draw the triangle !        glDrawArrays(GL_TRIANGLES, 0, vertices.size() );        glDisableVertexAttribArray(0);        glDisableVertexAttribArray(1);        // Swap buffers        glfwSwapBuffers(window);        glfwPollEvents();    } // Check if the ESC key was pressed or the window was closed    while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&           glfwWindowShouldClose(window) == 0 );    // Cleanup VBO and shader    glDeleteBuffers(1, &vertexbuffer);    glDeleteBuffers(1, &uvbuffer);    glDeleteProgram(programID);    glDeleteTextures(1, &TextureID);    glDeleteVertexArrays(1, &VertexArrayID);    // Close OpenGL window and terminate GLFW    glfwTerminate();    return 0;}

 

2. common/objloader.cpp

#include <vector>#include <stdio.h>#include <string>#include <cstring>#include <glm/glm.hpp>#include "objloader.hpp"// Very, VERY simple OBJ loader.// Here is a short list of features a real function would provide : // - Binary files. Reading a model should be just a few memcpy‘s away, not parsing a file at runtime. In short : OBJ is not very great.// - Animations & bones (includes bones weights)// - Multiple UVs// - All attributes should be optional, not "forced"// - More stable. Change a line in the OBJ file and it crashes.// - More secure. Change another line and you can inject code.// - Loading from memory, stream, etcbool loadOBJ(    const char * path,     std::vector<glm::vec3> & out_vertices,     std::vector<glm::vec2> & out_uvs,    std::vector<glm::vec3> & out_normals){    printf("Loading OBJ file %s...\n", path);    std::vector<unsigned int> vertexIndices, uvIndices, normalIndices;    std::vector<glm::vec3> temp_vertices;     std::vector<glm::vec2> temp_uvs;    std::vector<glm::vec3> temp_normals;    FILE * file = fopen(path, "r");    if( file == NULL ){        printf("Impossible to open the file ! Are you in the right path ? See Tutorial 1 for details\n");        getchar();        return false;    }    while( 1 ){        char lineHeader[128];        // read the first word of the line        int res = fscanf(file, "%s", lineHeader);        if (res == EOF)            break; // EOF = End Of File. Quit the loop.        // else : parse lineHeader                if ( strcmp( lineHeader, "v" ) == 0 ){            glm::vec3 vertex;            fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z );            temp_vertices.push_back(vertex);        }else if ( strcmp( lineHeader, "vt" ) == 0 ){            glm::vec2 uv;            fscanf(file, "%f %f\n", &uv.x, &uv.y );            uv.y = -uv.y; // Invert V coordinate since we will only use DDS texture, which are inverted. Remove if you want to use TGA or BMP loaders.            temp_uvs.push_back(uv);        }else if ( strcmp( lineHeader, "vn" ) == 0 ){            glm::vec3 normal;            fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z );            temp_normals.push_back(normal);        }else if ( strcmp( lineHeader, "f" ) == 0 ){            std::string vertex1, vertex2, vertex3;            unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];            int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2] );            if (matches != 9){                printf("File can‘t be read by our simple parser :-( Try exporting with other options\n");                return false;            }            vertexIndices.push_back(vertexIndex[0]);            vertexIndices.push_back(vertexIndex[1]);            vertexIndices.push_back(vertexIndex[2]);            uvIndices    .push_back(uvIndex[0]);            uvIndices    .push_back(uvIndex[1]);            uvIndices    .push_back(uvIndex[2]);            normalIndices.push_back(normalIndex[0]);            normalIndices.push_back(normalIndex[1]);            normalIndices.push_back(normalIndex[2]);        }else{            // Probably a comment, eat up the rest of the line            char stupidBuffer[1000];            fgets(stupidBuffer, 1000, file);        }    }    // For each vertex of each triangle    for( unsigned int i=0; i<vertexIndices.size(); i++ ){        // Get the indices of its attributes        unsigned int vertexIndex = vertexIndices[i];        unsigned int uvIndex = uvIndices[i];        unsigned int normalIndex = normalIndices[i];                // Get the attributes thanks to the index        glm::vec3 vertex = temp_vertices[ vertexIndex-1 ];        glm::vec2 uv = temp_uvs[ uvIndex-1 ];        glm::vec3 normal = temp_normals[ normalIndex-1 ];                // Put the attributes in buffers        out_vertices.push_back(vertex);        out_uvs     .push_back(uv);        out_normals .push_back(normal);        }    return true;}#ifdef USE_ASSIMP // don‘t use this #define, it‘s only for me (it AssImp fails to compile on your machine, at least all the other tutorials still work)// Include AssImp#include <assimp/Importer.hpp>      // C++ importer interface#include <assimp/scene.h>           // Output data structure#include <assimp/postprocess.h>     // Post processing flagsbool loadAssImp(    const char * path,     std::vector<unsigned short> & indices,    std::vector<glm::vec3> & vertices,    std::vector<glm::vec2> & uvs,    std::vector<glm::vec3> & normals){    Assimp::Importer importer;    const aiScene* scene = importer.ReadFile(path, 0/*aiProcess_JoinIdenticalVertices | aiProcess_SortByPType*/);    if( !scene) {        fprintf( stderr, importer.GetErrorString());        getchar();        return false;    }    const aiMesh* mesh = scene->mMeshes[0]; // In this simple example code we always use the 1rst mesh (in OBJ files there is often only one anyway)    // Fill vertices positions    vertices.reserve(mesh->mNumVertices);    for(unsigned int i=0; i<mesh->mNumVertices; i++){        aiVector3D pos = mesh->mVertices[i];        vertices.push_back(glm::vec3(pos.x, pos.y, pos.z));    }    // Fill vertices texture coordinates    uvs.reserve(mesh->mNumVertices);    for(unsigned int i=0; i<mesh->mNumVertices; i++){        aiVector3D UVW = mesh->mTextureCoords[0][i]; // Assume only 1 set of UV coords; AssImp supports 8 UV sets.        uvs.push_back(glm::vec2(UVW.x, UVW.y));    }    // Fill vertices normals    normals.reserve(mesh->mNumVertices);    for(unsigned int i=0; i<mesh->mNumVertices; i++){        aiVector3D n = mesh->mNormals[i];        normals.push_back(glm::vec3(n.x, n.y, n.z));    }    // Fill face indices    indices.reserve(3*mesh->mNumFaces);    for (unsigned int i=0; i<mesh->mNumFaces; i++){        // Assume the model has only triangles.        indices.push_back(mesh->mFaces[i].mIndices[0]);        indices.push_back(mesh->mFaces[i].mIndices[1]);        indices.push_back(mesh->mFaces[i].mIndices[2]);    }        // The "scene" pointer will be deleted automatically by "importer"}#endif

 

3.common/objloader.hpp

#ifndef OBJLOADER_H#define OBJLOADER_Hbool loadOBJ(    const char * path,     std::vector<glm::vec3> & out_vertices,     std::vector<glm::vec2> & out_uvs,     std::vector<glm::vec3> & out_normals);bool loadAssImp(    const char * path,     std::vector<unsigned short> & indices,    std::vector<glm::vec3> & vertices,    std::vector<glm::vec2> & uvs,    std::vector<glm::vec3> & normals);#endif

 

4. common/controls.cpp

// Include GLFW#include <glfw3.h>extern GLFWwindow* window; // The "extern" keyword here is to access the variable "window" declared in tutorialXXX.cpp. This is a hack to keep the tutorials simple. Please avoid this.// Include GLM#include <glm/glm.hpp>#include <glm/gtc/matrix_transform.hpp>using namespace glm;#include "controls.hpp"glm::mat4 ViewMatrix;glm::mat4 ProjectionMatrix;glm::mat4 getViewMatrix(){    return ViewMatrix;}glm::mat4 getProjectionMatrix(){    return ProjectionMatrix;}// Initial position : on +Zglm::vec3 position = glm::vec3( 0, 0, 5 ); // Initial horizontal angle : toward -Zfloat horizontalAngle = 3.14f;// Initial vertical angle : nonefloat verticalAngle = 0.0f;// Initial Field of Viewfloat initialFoV = 45.0f;float speed = 3.0f; // 3 units / secondfloat mouseSpeed = 0.005f;void computeMatricesFromInputs(){    // glfwGetTime is called only once, the first time this function is called    static double lastTime = glfwGetTime();    // Compute time difference between current and last frame    double currentTime = glfwGetTime();    float deltaTime = float(currentTime - lastTime);    // Get mouse position    double xpos, ypos;    glfwGetCursorPos(window, &xpos, &ypos);    // Reset mouse position for next frame    glfwSetCursorPos(window, 1024/2, 768/2);    // Compute new orientation    horizontalAngle += mouseSpeed * float(1024/2 - xpos );    verticalAngle   += mouseSpeed * float( 768/2 - ypos );    // Direction : Spherical coordinates to Cartesian coordinates conversion    glm::vec3 direction(        cos(verticalAngle) * sin(horizontalAngle),         sin(verticalAngle),        cos(verticalAngle) * cos(horizontalAngle)    );        // Right vector    glm::vec3 right = glm::vec3(        sin(horizontalAngle - 3.14f/2.0f),         0,        cos(horizontalAngle - 3.14f/2.0f)    );        // Up vector    glm::vec3 up = glm::cross( right, direction );    // Move forward    if (glfwGetKey( window, GLFW_KEY_UP ) == GLFW_PRESS){        position += direction * deltaTime * speed;    }    // Move backward    if (glfwGetKey( window, GLFW_KEY_DOWN ) == GLFW_PRESS){        position -= direction * deltaTime * speed;    }    // Strafe right    if (glfwGetKey( window, GLFW_KEY_RIGHT ) == GLFW_PRESS){        position += right * deltaTime * speed;    }    // Strafe left    if (glfwGetKey( window, GLFW_KEY_LEFT ) == GLFW_PRESS){        position -= right * deltaTime * speed;    }    float FoV = initialFoV;// - 5 * glfwGetMouseWheel(); // Now GLFW 3 requires setting up a callback for this. It‘s a bit too complicated for this beginner‘s tutorial, so it‘s disabled instead.    // Projection matrix : 45?Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units    ProjectionMatrix = glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 100.0f);    // Camera matrix    ViewMatrix       = glm::lookAt(                                position,           // Camera is here                                position+direction, // and looks here : at the same position, plus "direction"                                up                  // Head is up (set to 0,-1,0 to look upside-down)                           );    // For the next frame, the "last time" will be "now"    lastTime = currentTime;}

 
5.common/controls.hpp

#ifndef CONTROLS_HPP#define CONTROLS_HPPvoid computeMatricesFromInputs();glm::mat4 getViewMatrix();glm::mat4 getProjectionMatrix();#endif

 

6. common/texture.cpp

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <GL/glew.h>#include <glfw3.h>GLuint loadBMP_custom(const char * imagepath){    printf("Reading image %s\n", imagepath);    // Data read from the header of the BMP file    unsigned char header[54];    unsigned int dataPos;    unsigned int imageSize;    unsigned int width, height;    // Actual RGB data    unsigned char * data;    // Open the file    FILE * file = fopen(imagepath,"rb");    if (!file)                                {printf("%s could not be opened. Are you in the right directory ? Don‘t forget to read the FAQ !\n", imagepath); getchar(); return 0;}    // Read the header, i.e. the 54 first bytes    // If less than 54 bytes are read, problem    if ( fread(header, 1, 54, file)!=54 ){         printf("Not a correct BMP file\n");        return 0;    }    // A BMP files always begins with "BM"    if ( header[0]!=B || header[1]!=M ){        printf("Not a correct BMP file\n");        return 0;    }    // Make sure this is a 24bpp file    if ( *(int*)&(header[0x1E])!=0  )         {printf("Not a correct BMP file\n");    return 0;}    if ( *(int*)&(header[0x1C])!=24 )         {printf("Not a correct BMP file\n");    return 0;}    // Read the information about the image    dataPos    = *(int*)&(header[0x0A]);    imageSize  = *(int*)&(header[0x22]);    width      = *(int*)&(header[0x12]);    height     = *(int*)&(header[0x16]);    // Some BMP files are misformatted, guess missing information    if (imageSize==0)    imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component    if (dataPos==0)      dataPos=54; // The BMP header is done that way    // Create a buffer    data = http://www.mamicode.com/new unsigned char [imageSize];    // Read the actual data from the file into the buffer    fread(data,1,imageSize,file);    // Everything is in memory now, the file wan be closed    fclose (file);    // Create one OpenGL texture    GLuint textureID;    glGenTextures(1, &textureID);        // "Bind" the newly created texture : all future texture functions will modify this texture    glBindTexture(GL_TEXTURE_2D, textureID);    // Give the image to OpenGL    glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);    // OpenGL has now copied the data. Free our own version    delete [] data;    // Poor filtering, or ...    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);     // ... nice trilinear filtering.    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_MAG_FILTER, GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);     glGenerateMipmap(GL_TEXTURE_2D);    // Return the ID of the texture we just created    return textureID;}// Since GLFW 3, glfwLoadTexture2D() has been removed. You have to use another texture loading library, // or do it yourself (just like loadBMP_custom and loadDDS)//GLuint loadTGA_glfw(const char * imagepath){////    // Create one OpenGL texture//    GLuint textureID;//    glGenTextures(1, &textureID);////    // "Bind" the newly created texture : all future texture functions will modify this texture//    glBindTexture(GL_TEXTURE_2D, textureID);////    // Read the file, call glTexImage2D with the right parameters//    glfwLoadTexture2D(imagepath, 0);////    // Nice trilinear filtering.//    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_MAG_FILTER, GL_LINEAR);//    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); //    glGenerateMipmap(GL_TEXTURE_2D);////    // Return the ID of the texture we just created//    return textureID;//}#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCIIGLuint loadDDS(const char * imagepath){    unsigned char header[124];    FILE *fp;      /* try to open the file */     fp = fopen(imagepath, "rb");     if (fp == NULL){        printf("%s could not be opened. Are you in the right directory ? Don‘t forget to read the FAQ !\n", imagepath); getchar();         return 0;    }       /* verify the type of file */     char filecode[4];     fread(filecode, 1, 4, fp);     if (strncmp(filecode, "DDS ", 4) != 0) {         fclose(fp);         return 0;     }        /* get the surface desc */     fread(&header, 124, 1, fp);     unsigned int height      = *(unsigned int*)&(header[8 ]);    unsigned int width         = *(unsigned int*)&(header[12]);    unsigned int linearSize     = *(unsigned int*)&(header[16]);    unsigned int mipMapCount = *(unsigned int*)&(header[24]);    unsigned int fourCC      = *(unsigned int*)&(header[80]);     unsigned char * buffer;    unsigned int bufsize;    /* how big is it going to be including all mipmaps? */     bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;     buffer = (unsigned char*)malloc(bufsize * sizeof(unsigned char));     fread(buffer, 1, bufsize, fp);     /* close the file pointer */     fclose(fp);    unsigned int components  = (fourCC == FOURCC_DXT1) ? 3 : 4;     unsigned int format;    switch(fourCC)     {     case FOURCC_DXT1:         format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;         break;     case FOURCC_DXT3:         format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;         break;     case FOURCC_DXT5:         format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;         break;     default:         free(buffer);         return 0;     }    // Create one OpenGL texture    GLuint textureID;    glGenTextures(1, &textureID);    // "Bind" the newly created texture : all future texture functions will modify this texture    glBindTexture(GL_TEXTURE_2D, textureID);    glPixelStorei(GL_UNPACK_ALIGNMENT,1);            unsigned int blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;     unsigned int offset = 0;    /* load the mipmaps */     for (unsigned int level = 0; level < mipMapCount && (width || height); ++level)     {         unsigned int size = ((width+3)/4)*((height+3)/4)*blockSize;         glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height,              0, size, buffer + offset);              offset += size;         width  /= 2;         height /= 2;         // Deal with Non-Power-Of-Two textures. This code is not included in the webpage to reduce clutter.        if(width < 1) width = 1;        if(height < 1) height = 1;    }     free(buffer);     return textureID;}

 

7.common/texture.hpp

#ifndef TEXTURE_HPP#define TEXTURE_HPP// Load a .BMP file using our custom loaderGLuint loadBMP_custom(const char * imagepath);//// Since GLFW 3, glfwLoadTexture2D() has been removed. You have to use another texture loading library, //// or do it yourself (just like loadBMP_custom and loadDDS)//// Load a .TGA file using GLFW‘s own loader//GLuint loadTGA_glfw(const char * imagepath);// Load a .DDS file using GLFW‘s own loaderGLuint loadDDS(const char * imagepath);#endif

 

8. common/shader.cpp

#include <stdio.h>#include <string>#include <vector>#include <iostream>#include <fstream>#include <algorithm>using namespace std;#include <stdlib.h>#include <string.h>#include <GL/glew.h>#include "shader.hpp"GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){    // Create the shaders    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);    // Read the Vertex Shader code from the file    std::string VertexShaderCode;    std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);    if(VertexShaderStream.is_open()){        std::string Line = "";        while(getline(VertexShaderStream, Line))            VertexShaderCode += "\n" + Line;        VertexShaderStream.close();    }else{        printf("Impossible to open %s. Are you in the right directory ? Don‘t forget to read the FAQ !\n", vertex_file_path);        getchar();        return 0;    }    // Read the Fragment Shader code from the file    std::string FragmentShaderCode;    std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);    if(FragmentShaderStream.is_open()){        std::string Line = "";        while(getline(FragmentShaderStream, Line))            FragmentShaderCode += "\n" + Line;        FragmentShaderStream.close();    }    GLint Result = GL_FALSE;    int InfoLogLength;    // Compile Vertex Shader    printf("Compiling shader : %s\n", vertex_file_path);    char const * VertexSourcePointer = VertexShaderCode.c_str();    glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);    glCompileShader(VertexShaderID);    // Check Vertex Shader    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);    if ( InfoLogLength > 0 ){        std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);        glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);        printf("%s\n", &VertexShaderErrorMessage[0]);    }    // Compile Fragment Shader    printf("Compiling shader : %s\n", fragment_file_path);    char const * FragmentSourcePointer = FragmentShaderCode.c_str();    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);    glCompileShader(FragmentShaderID);    // Check Fragment Shader    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);    if ( InfoLogLength > 0 ){        std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);        glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);        printf("%s\n", &FragmentShaderErrorMessage[0]);    }    // Link the program    printf("Linking program\n");    GLuint ProgramID = glCreateProgram();    glAttachShader(ProgramID, VertexShaderID);    glAttachShader(ProgramID, FragmentShaderID);    glLinkProgram(ProgramID);    // Check the program    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);    if ( InfoLogLength > 0 ){        std::vector<char> ProgramErrorMessage(InfoLogLength+1);        glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);        printf("%s\n", &ProgramErrorMessage[0]);    }        glDetachShader(ProgramID, VertexShaderID);    glDetachShader(ProgramID, FragmentShaderID);        glDeleteShader(VertexShaderID);    glDeleteShader(FragmentShaderID);    return ProgramID;}

 

9.common/shader.hpp

#ifndef SHADER_HPP#define SHADER_HPPGLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path);#endif

 

10.shaders/TransformVertexShader.vertexshader

#version 330 core// Input vertex data, different for all executions of this shader.layout(location = 0) in vec3 vertexPosition_modelspace;layout(location = 1) in vec2 vertexUV;// Output data ; will be interpolated for each fragment.out vec2 UV;// Values that stay constant for the whole mesh.uniform mat4 MVP;void main(){    // Output position of the vertex, in clip space : MVP * position    gl_Position =  MVP * vec4(vertexPosition_modelspace,1);        // UV of the vertex. No special space for this one.    UV = vertexUV;}

 

11.shaders/TextureFragmentShader.fragmentshader

#version 330 core// Interpolated values from the vertex shadersin vec2 UV;// Ouput dataout vec3 color;// Values that stay constant for the whole mesh.uniform sampler2D myTextureSampler;void main(){    // Output color = color of the texture at the specified UV    color = texture( myTextureSampler, UV ).rgb;}

 

技术分享

OpenGL学习--07--模型加载(obj)