2016-03-04 69 views
0

據我瞭解,頂點提取階段被VAO封裝,並且VAO需要包含緩衝區對象和頂點屬性之間的管道的頂點提取階段狀態以及格式化緩衝區對象中的數據。不需要有一個VAO?

這兩本書,我一直在閱讀關於這個問題i.Red書,藍皮書都明確提及當VAO必須包含頂點獲取階段狀態數據

但是當我真正創建2個紋理對象,只是格式數據一次沒有一個VAO存儲這個緩衝區的信息,它仍然運行良好沒有任何打嗝,然後我重新加載第一個對象回來,再次它沒有任何問題,它工作正常,所以這個信息從哪裏拉出來關於緩衝區對象中數據的格式?

我甚至第二次上傳緩衝區數據到相同的緩衝區對象,這意味着以前的信息將被重置?並且圖片仍然呈現在窗口上

那到底究竟是怎麼回事?書中說了一件事情,現實中發生的事情是完全不同的,相反

有人能真正解釋什麼是真正需要在這裏,什麼是不是?究竟發生了什麼?

我們什麼時候需要一個VAO,什麼時候我們可以不用? 當不需要額外的代碼處理時,它有什麼意義?

下面的代碼:

int main(){ 

    int scrW=1280, scrH=720; 

    //create context and shader program 
    init(scrW, scrH); 
    createShaders(); 

    //create texture objects and load data from image to server memory 
    char object[2][25]; 
    strcpy(object[0], "back.bmp"); 
    strcpy(object[1], "256x256.bmp"); 


    //triangle 1 
    GLfloat vertices[] = 
    // X  Y  U V 
    { -1.0, -1.0, 0.0, 0.0, 
     1.0, -1.0, 1.0, 0.0, 
     1.0, 1.0, 1.0, 1.0, 
     -1.0, 1.0, 0.0, 1.0}; 


    //glPointSize(40.0f); 

    //create and bound vertex buffer object(memory buffers) 
    GLuint vbo1 = createVbo(); 

    //The state set by glVertexAttribPointer() is stored in the currently bound vertex array object (VAO) if vertex array object bound 
    //associates the format of the data for the currently bound buffer object to the vertex attribute so opengl knows how much and how to read it 
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0); 
    glEnableVertexAttribArray(0); 

    //shader vertex attribute for texture coordinates 
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (const GLvoid*)(2 * sizeof(GLfloat))); 
    glEnableVertexAttribArray(1); 

    //upload vertices to buffer memory 
    //will upload data to currently bound/active buffer object 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 

    //load and create texture object from image data 
    GLuint tex1 = createTexture(object[0]); 

    glDrawArrays(GL_QUADS, 0, 4); 

    glXSwapBuffers (dpy, glxWin); 
    sleep(3); 


    GLuint tex2 = createTexture(object[1]); 

    glDrawArrays(GL_QUADS, 0, 4); 


    glXSwapBuffers (dpy, glxWin); 
    sleep(3); 

    glBindTexture(GL_TEXTURE_2D, tex1); 

    glDrawArrays(GL_QUADS, 0, 4); 


    glXSwapBuffers (dpy, glxWin); 
    sleep(3); 


    //////////////de-initialize 
    glXMakeContextCurrent(dpy, 0, 0, NULL); 
    glXDestroyContext(dpy, context); 
    glXDestroyWindow(dpy, glxWin); 
    XDestroyWindow(dpy, win); 
    XCloseDisplay(dpy); 

    return 0; 
} 

和着色器

const char* vertex_shader = 
     "#version 400\n" 
     "layout(location = 0) in vec2 vp;" 
     "layout(location = 1) in vec2 tex;" 
     "out vec2 texCoord;" 
     "void main() {" 
     " gl_Position = vec4 (vp, 0.0f, 1.0f);" 
     " texCoord = tex; " 
     "}"; 

    const char* fragment_shader = 
     "#version 400\n" 
     "uniform sampler2D s;" 
     "in vec2 texCoord;" 
     "out vec4 color;" 
     "void main() {" 
     "color = texture(s, texCoord);" 
     "}"; 

,以避免任何混淆,這裏是init()方法

static int att[] = 
    { 
     GLX_X_RENDERABLE , True, 
     GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, 
     GLX_RENDER_TYPE  , GLX_RGBA_BIT, 
     GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, 
     GLX_RED_SIZE  , 8, 
     GLX_GREEN_SIZE  , 8, 
     GLX_BLUE_SIZE  , 8, 
     GLX_ALPHA_SIZE  , 8, 
     GLX_DEPTH_SIZE  , 24, 
     GLX_STENCIL_SIZE , 8, 
     GLX_DOUBLEBUFFER , True, 
     //GLX_SAMPLE_BUFFERS , 1, 
     //GLX_SAMPLES   , 4, 
     None 
    }; 

    Display       *dpy; 
    Window       root; 
    XVisualInfo      *vi; 
    Colormap       cmap; 
    XSetWindowAttributes    swa; 
    Window       win; 
    GLXContext      context; 
    GLXFBConfig      *fbc; 
    GLXWindow       glxWin; 
    int        fbcount; 


void init(int width, int height){ 

    //set and choose displays for creating window 
    dpy = XOpenDisplay(NULL); 
    if (!dpy){ 
     printf("Failed to open X display\n"); 
     exit(1); 
    } 

    root = DefaultRootWindow(dpy); 

    //request a framebuffer configuration 
    fbc = glXChooseFBConfig(dpy, DefaultScreen(dpy), att, &fbcount); 

    if (!fbc){ 
     printf("Failed to retrieve a framebuffer config\n"); 
     exit(1); 
    } 

    vi = glXGetVisualFromFBConfig(dpy, fbc[0]); 

    if(vi==NULL){ 
     printf("Error getting visual info\n"); 
     exit(1); 
    } 
    swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone); 

    swa.background_pixmap = None ; 
    swa.border_pixel   = 0; 
    swa.event_mask   = StructureNotifyMask; 

    //Window XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valuemask, attributes) 

    win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa); 
    if (!win){ 
     printf("Failed to create window.\n"); 
     exit(1); 
    } 

    context = glXCreateNewContext(dpy, fbc[0], GLX_RGBA_TYPE, NULL, True); 

    glxWin = glXCreateWindow(dpy, fbc[0], win, NULL); 

    XMapWindow(dpy, win); 

    glXMakeContextCurrent(dpy, glxWin, glxWin, context); 

    // start GLEW extension handler 
    glewExperimental = GL_TRUE; 
    GLuint err = glewInit(); 

    if(err!=GLEW_OK){ 
     fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); 
     exit(1); 
    } 


    XSelectInput(dpy, win, ButtonPressMask|KeyPressMask); 

    // tell GL to only draw onto a pixel if the shape is closer to the viewer 
    //glEnable (GL_DEPTH_TEST); // enable depth-testing 
    //glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" 


} 

回答

2

如果使用兼容OpenGL上下文,你不需要一個VAO。從某種意義上說,有一個總是受約束的「默認」VAO。這就是它在OpenGL 2.x中的工作原理,這是「兼容性」在「兼容性配置文件」中的含義。

在您使用核心OpenGL上下文時,您確實需要一個VAO。如果你不這樣做,你的代碼根本無法工作。如果你想繼續假裝你不需要一個VAO,你可以創建一個VAO並在整個程序期間綁定它。

選擇核心與兼容性配置文件的問題有其細微之處,但總的來說,如果您正在開發新程序,建議您請求核心配置文件。不是所有的系統都支持兼容性配置文件。 Mesa將兼容性配置文件限制爲3.0,OS X將其限制爲2.1。如果您需要核心配置文件,則在創建上下文時必須明確請求核心配置文件。

+0

對不起,我真的不明白你在談論什麼我有什麼問題? 我正在使用核心配置文件opengl,但我的問題不是關於那個,而是關於VAO的,你沒有在你的回答中解決所有問題 – hopjopper

+1

@hopjopper是什麼讓你如此相信你有一個核心配置文件的上下文?我在發佈的代碼中沒有看到特別要求核心上下文的任何內容。 –

+0

以及我相信,兼容性配置文件不是默認的,並被要求,而核心配置文件是默認的,我真的不知道你爲什麼試圖回答一個假設的問題,誠實地..... – hopjopper