代码之家  ›  专栏  ›  技术社区  ›  Kevin Su

无法在opengl中正确绘制我的汽车

  •  1
  • Kevin Su  · 技术社区  · 7 年前

    这是我的主要任务。cpp,我想画一辆车,我从obj文件中获取数据,然后放入着色器。我将obj文件放入meshlab,它绘制正确-> Image ,但在我的c++中会这样-> Image

    #include "..\tinyobjloader\tiny_obj_loader.h"
    #include <algorithm>
    #include <iostream>
    #include<glew.h>
    #include <glut.h>
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    #include <chrono>
    #include<SOIL.h>
    #include<math.h>
    #include"Shader.h"
    
    GLuint programHandle;
    GLuint vShader, fShader;   
    static GLuint g_TexName;
    GLuint vaoHandle;
    std::vector<GLfloat> vertices;
    std::vector<GLfloat>  colorData;
    std::vector<GLfloat> texCoords;
    std::vector<unsigned int> elements;
    
    tinyobj::attrib_t attrib;
    std::vector<tinyobj::shape_t> shapes;
    std::vector<tinyobj::material_t> materials;
    
    GLuint vboHandles[4];
    GLuint elementbuffer;
    
    GLuint positionBufferHandle = vboHandles[0];    
    GLuint colorBufferHandle = vboHandles[1];
    GLuint textureBufferHandle = vboHandles[2];
    GLuint mvphandle = vboHandles[3];
    
    unsigned char * data;
    using namespace std;
    
    float t = 0.0;
    float maxs = 0;
    
    void  initShader(const char  *VShaderFile, const char  *FShaderFile)
    {
        //1、查看GLSL和OpenGL的版本  
        const  GLubyte *renderer = glGetString(GL_RENDERER);
        const  GLubyte *vendor = glGetString(GL_VENDOR);
        const  GLubyte *version = glGetString(GL_VERSION);
        const  GLubyte *glslVersion =
            glGetString(GL_SHADING_LANGUAGE_VERSION);
        GLint major, minor;
        glGetIntegerv(GL_MAJOR_VERSION, &major);
        glGetIntegerv(GL_MINOR_VERSION, &minor);
        //cout << "GL Vendor :" << vendor << endl;
        //cout << "GL Renderer : " << renderer << endl;
        //cout << "GL Version (string) : " << version << endl;
        //cout << "GL Version (integer) : " << major << "." << minor << endl;
        //cout << "GLSL Version : " << glslVersion << endl;
    
                vShader = glCreateShader(GL_VERTEX_SHADER);
    
        if (0 == vShader)
        {
            cerr << "ERROR : Create vertex shader failed" << endl;
            exit(1);
        }
    
        const  GLchar *vShaderCode = textFileRead(VShaderFile);
        const  GLchar *vCodeArray[1] = { vShaderCode };
        glShaderSource(vShader, 1, vCodeArray, NULL);
    
        glCompileShader(vShader);
    
    
    
        GLint compileResult;
        glGetShaderiv(vShader, GL_COMPILE_STATUS, &compileResult);
        if (GL_FALSE == compileResult)
        {
            GLint logLen;
    
            glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &logLen);
            if (logLen > 0)
            {
                char  *log = (char  *)malloc(logLen);
                GLsizei written;
    
                glGetShaderInfoLog(vShader, logLen, &written, log);
                cerr << "vertex shader compile log : " << endl;
                cerr << log << endl;
                free(log); 
            }
        }
    
    
        fShader = glCreateShader(GL_FRAGMENT_SHADER);
    
        if (0 == fShader)
        {
            cerr << "ERROR : Create fragment shader failed" << endl;
            exit(1);
        }
    
    
        const  GLchar *fShaderCode = textFileRead(FShaderFile);
        const  GLchar *fCodeArray[1] = { fShaderCode };
        glShaderSource(fShader, 1, fCodeArray, NULL);
    
    
        glCompileShader(fShader);
    
    
        glGetShaderiv(fShader, GL_COMPILE_STATUS, &compileResult);
        if (GL_FALSE == compileResult)
        {
            GLint logLen;
    
            glGetShaderiv(fShader, GL_INFO_LOG_LENGTH, &logLen);
            if (logLen > 0)
            {
                char  *log = (char  *)malloc(logLen);
                GLsizei written;
    
                glGetShaderInfoLog(fShader, logLen, &written, log);
                cerr << "fragment shader compile log : " << endl;
                cerr << log << endl;
                free(log);  
            }
        }
    
    
        //GLuint programHandle = glCreateProgram();
        programHandle = glCreateProgram();
        if (!programHandle)
        {
            cerr << "ERROR : create program failed" << endl;
            exit(1);
        }
    
        glAttachShader(programHandle, vShader);
        glAttachShader(programHandle, fShader);
    
        glLinkProgram(programHandle);
    
        GLint linkStatus;
        glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus);
        if (GL_FALSE == linkStatus)
        {
            cerr << "ERROR : link shader program failed" << endl;
            GLint logLen;
            glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH,
                &logLen);
            if (logLen > 0)
            {
                char  *log = (char  *)malloc(logLen);
                GLsizei written;
                glGetProgramInfoLog(programHandle, logLen,
                    &written, log);
                cerr << "Program log : " << endl;
                cerr << log << endl;
            }
        }
        else   
        {
            glUseProgram(programHandle);
        }
    }
    void LoadTexture(){
        // Load texture
        errno_t err;
        // 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
    
    
        int width, height, nrChannels;
        //data = SOIL_load_image("wall.bmp", &width, &height, 0, SOIL_LOAD_RGB);
    
        FILE *  file;
        const char imagepath[] = "Van.bmp";
        if (err = fopen_s(&file, imagepath, "rb")){ printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); }
        if (fread(header, 1, 54, file) != 54){
            printf("Not a correct BMP file\n");
        }
        // A BMP files always begins with "BM"
        if (header[0] != 'B' || header[1] != 'M'){
            printf("Not a correct BMP file\n");
        }
        // Make sure this is a 24bpp file
        if (*(int*)&(header[0x1E]) != 0)         { printf("Not a correct BMP file\n"); }
        if (*(int*)&(header[0x1C]) != 24)         { printf("Not a correct BMP file\n"); }
    
        dataPos = *(int*)&(header[0x0A]);
        imageSize = *(int*)&(header[0x22]);
        width = *(int*)&(header[0x12]);
        height = *(int*)&(header[0x16]);
        printf("width : %d   hight : %d\n", width, height);
        data = new unsigned char[imageSize];
        cout << imageSize << endl;
    
        // 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);
    
        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);
    
    
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, textureID);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        glUniform1i(glGetUniformLocation(programHandle, "tex"), 0);
    
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    }
    void  initVBO()
    {
        glGenVertexArrays(1, &vaoHandle);
        glBindVertexArray(vaoHandle);
        glGenBuffers(3, vboHandles);
        GLuint positionBufferHandle = vboHandles[0];
        GLuint colorBufferHandle = vboHandles[1];
        GLuint textureBufferHandle = vboHandles[2];
    
    
        glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
        glBufferData(GL_ARRAY_BUFFER, attrib.vertices.size(),&vertices[0], GL_STATIC_DRAW);
    
        glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle); 
        glBufferData(GL_ARRAY_BUFFER, attrib.colors.size(),&colorData[0], GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, textureBufferHandle);
        if (texCoords.size()>0)
            glBufferData(GL_ARRAY_BUFFER, attrib.texcoords.size(),&texCoords[0], GL_STATIC_DRAW);
    
        glGenBuffers(1, &elementbuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
    
        //glBufferData(GL_ELEMENT_ARRAY_BUFFER, shapes[0].mesh.num_face_vertices.size() , &elements[0], GL_STATIC_DRAW);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, elements.size()*sizeof(unsigned int), &elements[0], GL_STATIC_DRAW);
        cout << "element*sizeof(unsigned int) = " << elements.size()*sizeof(unsigned int) << endl;
    
        glEnableVertexAttribArray(0); //頂點坐標  
        glEnableVertexAttribArray(1); //頂點顏色 
        glEnableVertexAttribArray(2); //texture
    
        glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    
        glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    
        glBindBuffer(GL_ARRAY_BUFFER, textureBufferHandle);
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
    
        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
    }
    void  init()
    {
        GLenum err = glewInit();
        if (GLEW_OK != err)
        {
            std::cout << "Error initializing GLEW: " << glewGetErrorString(err) << std::endl;
        }
    
        initShader("vert.txt", "frag.txt");
    
        initVBO();
        LoadTexture();
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glShadeModel(GL_SMOOTH);
    
    }
    void  display()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        //cout << "display--> " << endl;
        //cout << vertices[0] << endl << vertices[1] << endl << vertices[2] << endl;
    
    
    
        t += 0.0001f;
        if (t >= 1)
            t = 0;
        // Set the camera
        glm::mat4 Projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 1.0f, 100.0f);
        //glm::mat4 Projection = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 0.0f, 10.0f); 
        glm::mat4 View = glm::lookAt(
            glm::vec3(2.5f, 2.0f, 3.0f),
            glm::vec3(0.0f, 0.0f, 0.0f),
            glm::vec3(0.0f, 0.0f, 1.0f)
            );
    
        glm::mat4 Model = glm::mat4(1.0f);
        Model = glm::rotate(
            Model,
            glm::radians(360.0f*t),
            glm::vec3(0.0f, 0.0f, 1.0f)
            );
        /*Model = glm::scale(
            glm::translate(Model, glm::vec3(0, 0, 0)),
            glm::vec3(2 / maxs, 2 / maxs, 2 / maxs)
            );*/
    
        GLuint MVP = glGetUniformLocation(programHandle, "mvp");
        glm::mat4 mvp = Projection*View*Model;
        glUniformMatrix4fv(MVP, 1, GL_FALSE, &mvp[0][0]);
    
        glBindVertexArray(vaoHandle);
        //glDrawArrays(GL_TRIANGLES, 0, attrib.vertices.size());
    
        //glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
        //glDrawElements(GL_TRIANGLES, attrib.vertices.size(), GL_UNSIGNED_INT, 0);
    
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
        //glBindVertexArray(0);
        //cout << shapes[0].mesh.num_face_vertices.size() << endl;
        glDrawElements(GL_TRIANGLES, elements.size() , GL_UNSIGNED_INT, (void*)0);
        //glDrawElements(GL_QUADS, elements.size(), GL_UNSIGNED_INT, (void*)0);
    
        glutSwapBuffers();
    }
    void Reshape(int w, int h)
    {
        if (h == 0)
            h = 1;
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(60, (GLfloat)w / (GLfloat)h, 0.1, 1000.0);
        //glOrtho(-25,25,-2,2,0.1,100);
        glMatrixMode(GL_MODELVIEW);
    }
    void  keyboard(unsigned  char  key, int  x, int  y)
    {
        switch (key)
        {
        case  27:
            glDeleteShader(vShader);
            glUseProgram(0);
            exit(0);
            break;
        }
    
    }
    
    void normalize(){
    
        std::vector<float> xVector, yVector, zVector;
        float minX = 0, maxX = 0, minY = 0, maxY = 0, minZ = 0, maxZ = 0;
    
        // find out min and max value of X, Y and Z axis
        for (int i = 0; i < attrib.vertices.size(); i++)
        {
            maxs = max(maxs, attrib.vertices.at(i));
            if (i % 3 == 0)
            {
    
                xVector.push_back(attrib.vertices.at(i));
    
                if (attrib.vertices.at(i) < minX)
                {
                    minX = attrib.vertices.at(i);
                }
    
                if (attrib.vertices.at(i) > maxX)
                {
                    maxX = attrib.vertices.at(i);
                }
            }
            else if (i % 3 == 1)
            {
                yVector.push_back(attrib.vertices.at(i));
    
                if (attrib.vertices.at(i) < minY)
                {
                    minY = attrib.vertices.at(i);
                }
    
                if (attrib.vertices.at(i) > maxY)
                {
                    maxY = attrib.vertices.at(i);
                }
            }
            else if (i % 3 == 2)
            {
                zVector.push_back(attrib.vertices.at(i));
    
                if (attrib.vertices.at(i) < minZ)
                {
                    minZ = attrib.vertices.at(i);
                }
    
                if (attrib.vertices.at(i) > maxZ)
                {
                    maxZ = attrib.vertices.at(i);
                }
            }*/
    
        }
    
        float offsetX = (maxX + minX) / 2;
        float offsetY = (maxY + minY) / 2;
        float offsetZ = (maxZ + minZ) / 2;
    
        /*for (int i = 0; i < attrib.vertices.size(); i++)
        {
            if (offsetX != 0 && i % 3 == 0)
            {
                attrib.vertices.at(i) = attrib.vertices.at(i) - offsetX;
            }
            else if (offsetY != 0 && i % 3 == 1)
            {
                attrib.vertices.at(i) = attrib.vertices.at(i) - offsetY;
            }
            else if (offsetZ != 0 && i % 3 == 2)
            {
                attrib.vertices.at(i) = attrib.vertices.at(i) - offsetZ;
            }
        }
    
    
        // Find out the greatest distance of three axis
        float greatestAxis = maxX - minX;
        float distanceOfYAxis = maxY - minY;
        float distanceOfZAxis = maxZ - minZ;
    
        if (distanceOfYAxis > greatestAxis)
        {
            greatestAxis = distanceOfYAxis;
        }
    
        if (distanceOfZAxis > greatestAxis)
        {
            greatestAxis = distanceOfZAxis;
        }
    
        greatestAxis = greatestAxis / 2;
    
    
    
            for (int i = 0; i < attrib.vertices.size(); i++)
            {
                //std::cout << i << " = " << (double)(attrib.vertices.at(i) / greatestAxis) << std::endl;
                attrib.vertices.at(i) = attrib.vertices.at(i) / greatestAxis;
                vertices.push_back(attrib.vertices.at(i));
            }
            for (int i = 0; i < attrib.colors.size(); i++)
                colorData.push_back(attrib.colors.at(i));
            for (int i = 0; i < attrib.texcoords.size(); i++)
                texCoords.push_back(attrib.texcoords.at(i));
    
            for (int k = 0; k < shapes.size(); k++){
                for (int i = 0; i < shapes[k].mesh.indices.size(); i++){
                elements.push_back(shapes[k].mesh.indices[i].vertex_index);
                //cout << i << " = " << shapes[0].mesh.indices[i].vertex_index<<endl;
                //elements.push_back(shapes[0].mesh.indices[i].texcoord_index);
                //elements.push_back(shapes[0].mesh.indices[i].normal_index);
            }
        }
        cout << "shapes[0].mesh.indices.size() = " << shapes[0].mesh.indices.size() << endl;
        //cout << "elements = " << elements[4750] << endl;
    }
    int main()
    {
        std::string err;
        bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "..//tinyobjloader//models//Van.obj",
            NULL, false);
        normalize();
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB |GLUT_DEPTH);
        glutInitWindowSize(800, 600);
        glutInitWindowPosition(100, 100);
        glutCreateWindow("GLSL Test : Draw a triangle");
        glutReshapeFunc(Reshape);
        init();
        glEnable(GL_DEPTH_TEST);
    
        //glDepthFunc(GL_LESS);
        glutDisplayFunc(display);
        glutKeyboardFunc(keyboard);
        glutIdleFunc(display);
        glutMainLoop();
    
        return  0;
    }
    

    这是我的顶点。着色器,我使用着色器编译器,没有错误。

    #version 400  
    in vec3 Color;  
    in vec2 texcoord;
    out vec4 FragColor;  
    uniform sampler2D tex;
    
    void  main()  
    {  
        FragColor =  texture(tex, vec2(texcoord.x,texcoord.y))*vec4(Color, 1.0);
        //FragColor = vec4(1, 0, 0, 1);
        //if(Color.x>=0)FragColor = vec4(Color, 1.0);
    }  
    

    这是我的片段。着色器,我使用着色器编译器,没有错误。

    #version 400  
    in vec3 Color;  
    in vec2 texcoord;
    out vec4 FragColor;  
    uniform sampler2D tex;
    
    void  main()  
    {  
        FragColor =  texture(tex, vec2(texcoord.x,texcoord.y))*vec4(Color, 1.0);
    }  
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   YesThatIsMyName Decu    7 年前

    我引用kevin su的评论:

    最后,我找到了答案。属性。顶点。size()应更改为sizeof(顶点)。属性。顶点。size()是点数,sizeof(顶点)是点数(points*sizeof(unsign int))。