2015-05-12 38 views
1

我是OpenGL的新手,一直關注Jeffrey Chastine的YouTube教程。作爲一個個人練習,我想用索引緩衝區做一個簡單的正方形。可悲的是,在我的嘗試中,我只看到一個三角形(當我期望兩個)時。我不確定我錯過了什麼。這是我的代碼,我試着在評論中解釋我的邏輯/推理。隨時糾正我只要我錯了:OpenGL索引緩衝製作廣場

#include <GL/glew.h> 
#include <GL/freeglut.h> 
#include <iostream> 

#define BUFFER_OFFSET(i) ((char *)NULL + (i)) 
GLuint shaderProgramID; 
GLuint vao = 0; 
GLuint vbo; 
GLuint positionID, colorID; 
GLuint indexBufferID; 


#pragma region SHADER_FUNCTIONS 

static char* readFile(const char* fileName) 
{ 
    //Open the file 
    FILE* fp = fopen(fileName, "r"); 

    //Move the file pointer to the end of the file and determining the length 
    fseek(fp, 0, SEEK_END); 
    long file_length = ftell(fp); 
    fseek(fp, 0, SEEK_SET); 
    char* contents = new char[file_length + 1]; 

    //zero out memory 
    for(int i = 0; i < file_length+1; i++) 
    { 
     contents[i] = 0; 
    } 

    //Here's the actual read 
    fread(contents, 1, file_length, fp); 
    contents[file_length + 1] = '\0'; 
    fclose(fp); 
    return contents; 
} 

bool compiledStatus(GLint shaderID){ 
    GLint compiled = 0; 
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compiled); 
    if (compiled) { 
     return true; 
    } 
    else { 
     GLint logLength; 
     glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength); 
     char* msgBuffer = new char[logLength]; 
     glGetShaderInfoLog(shaderID, logLength, NULL, msgBuffer); 
     printf ("%s\n", msgBuffer); 
     delete (msgBuffer); 
     return false; 
    } 
} 

//Takes in source code as string 
GLuint makeVertexShader(const char* shaderSource) 
{ 
    //Call GL to make a vertex shader and get the ID 
    GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER); 

    //Bind the provided source code to the shader ID 
    glShaderSource(vertexShaderID, 1, (const GLchar**)&shaderSource, NULL); 

    //Compile the vertex Shader 
    glCompileShader(vertexShaderID); 

    bool compiledCorrect = compiledStatus(vertexShaderID); 
    if(compiledCorrect) 
    { 
     return vertexShaderID; 
    } 
    return -1; 

    return vertexShaderID; 
} 

GLuint makeFragmentShader(const char* shaderSource) 
{ 
    //Call GL to make a fragment shader and get the ID 
    GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); 
    //Bind the provided source code to the shader ID 
    glShaderSource(fragmentShaderID, 1, (const GLchar**)&shaderSource, NULL); 
    //Compile the fragment Shader 
    glCompileShader(fragmentShaderID); 

    bool compiledCorrect = compiledStatus(fragmentShaderID); 
    if(compiledCorrect) 
    { 
     return fragmentShaderID; 
    } 
    return -1; 

    return fragmentShaderID; 
} 

#pragma endregion SHADER_FUNCTIONS 

void changeViewport(int w, int h) 
{ 
    glViewport(0, 0, w, h); 
} 

//This is the function we are using each time the window needs to be redrawn 
void render() 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_INT, NULL); 
    glutSwapBuffers(); 
} 

GLuint makeShaderProgram(GLuint vertextShaderID, GLuint fragmentShaderID) 
{ 
    GLuint shaderID = glCreateProgram(); 
    //Attach the vertex shader to the shader program 
    glAttachShader(shaderID, vertextShaderID); 

    //Attatch the fragment shader to the shader program 
    glAttachShader(shaderID, fragmentShaderID); 

    //Link all the shaders together 
    glLinkProgram(shaderID); 
    return shaderID; 
} 

int main (int argc, char** argv) 
{ 
    //Standards 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_RGBA); 
    glutInitWindowSize(800, 600); 
    glutCreateWindow("Test"); 
    glutReshapeFunc(changeViewport); 
    glutDisplayFunc(render); 
    glewInit(); 

    //Verticies 
    GLfloat vertices_0[] = {-0.5f, -0.5f, 0.0f, //0 -> Bottom Left 
          -0.5f, 0.5f, 0.0f, //1 -> Top Left 
          0.5f, -0.5f, 0.0f, //2 -> Bottom Right 
          0.05f, 0.5f, 0.0f};//3 -> Top Right 
    //Colors 
    GLfloat colors_0[] = {1.0f, 0.0, 0.0f, 1.0f,//0 
          0.0f, 1.0f, 0.0f, 1.0f,//1 
          0.0f, 0.0f, 1.0f, 1.0f,//2 
          1.0f, 0.0f, 1.0f, 1.0f};//3 

    //Indicies -> Triangle 1 -> 0 1 2, Traingle 2 -> 1 3 2 
    GLuint indicies_0[] = {0, 1, 2, 1, 3, 2}; 


    //Read the vertex shader 
    char* vertexShaderSourceCode = readFile("vertexShader.vsh"); 

    //Read the fragment shader 
    char* fragmentShaderSourceCode = readFile("fragmentShader.fsh"); 

    //Make Vertex Shader 
    GLuint vertexShaderID = makeVertexShader(vertexShaderSourceCode); 

    //Make Fragment Shader 
    GLuint fragmentShaderID = makeFragmentShader(fragmentShaderSourceCode); 

    //Make Shader Program 
    shaderProgramID = makeShaderProgram(vertexShaderID, fragmentShaderID); 


    printf("Vertex Shader ID is %d\n", vertexShaderID); 
    printf("Fragment Shader ID is %d\n", fragmentShaderID); 
    printf("Shader Program ID is %d\n", shaderProgramID); 
    printf("s_vPosition's ID is %d\n", positionID); 

    //Create vertex array object 
    glGenVertexArrays(1, &vao); 

    //Bind Vertex array object 
    glBindVertexArray(vao); 

    //Create vertex buffer object 
    glGenBuffers(1, &vbo); 

    //Bind vertex buffer object 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 

    //Create Buffer ->7 Values for 4 vertices 
    glBufferData(GL_ARRAY_BUFFER, 7*4*sizeof(GLfloat), NULL, GL_STATIC_DRAW); 

    //Starting at the beggining of the buffer, place the position data (3 values for 4 verticies) 
    glBufferSubData(GL_ARRAY_BUFFER, 0, 3*4*sizeof(GLfloat), vertices_0); 

    //Starting after the placement of position data, place the color data (4 values for 4 verticies) 
    glBufferSubData(GL_ARRAY_BUFFER, 3*4*sizeof(GLfloat), 4*4*sizeof(GLfloat), colors_0); 

    //Generate the index buffer 
    glGenBuffers(1, &indexBufferID); 

    //Bind the buffer 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID); 

    //Place index buffer data for the 6 indicies 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6*sizeof(GLuint), indicies_0, GL_STATIC_DRAW); 

    //Get the position attribute from the shader 
    positionID = glGetAttribLocation(shaderProgramID, "s_vPosition"); 

    //Get the color attribute from the shader 
    colorID = glGetAttribLocation(shaderProgramID, "s_vColor"); 

    //Tell the variables where they can find its info in the buffer 
    glVertexAttribPointer(positionID, 3, GL_FLOAT, GL_FALSE, 0, 0); 

    glVertexAttribPointer(colorID, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(vertices_0))); 

    //Tell the program to use the shader program 
    glUseProgram(shaderProgramID); 
    //Turn on the position variable in the shader 
    glEnableVertexAttribArray(positionID); 
    //Turn on the color variable in the shader 
    glEnableVertexAttribArray(colorID); 

    glutMainLoop(); 
    return 0; 
} 
+1

它當然不會是一個正方形,因爲其中一個座標是'0.05f'而不是'0.5f'。但它也不應該是一個三角形。 –

+0

感謝您指出這一點 – StaticGamedude

回答

3

正如在評論中提到,有一個錯誤在你的頂點定義(0.05f應該是0.5F)。

但是,你只看到一個三角形,而不是2的原因是這樣的線:

glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_INT, NULL); 

第二個參數是在OpenGL documentation作爲

計數描述 - 指定元素的數量被渲染。

它是索引計數(每個元素由索引數組中的條目引用),因此應該是索引數組中的條目數,而不是唯一索引的數量。因此,改變4到6

需要注意的是,如果你使用的GL_TRIANGLE_STRIPGL_TRIANGLE_FAN代替GL_TRIANGLES你只需要4個指標{0,1,2,3},你可以通過4,你在做什麼,因爲每個第一個三角形後的三角形與上一個三角形共享2個索引,總索引數爲(三角形數+ 2)。但是,使用GL_TRIANGLES時,每個三角形分別指定3個索引(三角形數* 3)。

+0

這是它,感謝您的幫助! – StaticGamedude