青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

黎明的剔透里伸出了你沁清的曖昧

Graphics|EngineDev|GameDev|2D&3D Art

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  60 隨筆 :: 1 文章 :: 18 評論 :: 0 Trackbacks

        OpenGL拋棄glEnable(),glColor(),glVertex(),glEnable()這一套流程的函數和管線以后,就需要一種新的方法來傳遞數據到Graphics Card來渲染幾何體,我們可以用VBO, 在3+版本我們可以使用Vertex Array Object-VAO,VAO是一個對象,其中包含一個或者更多的Vertex Buffer Objects。而VBO是Graphics Card中的一個內存緩沖區,用來保存頂點信息,顏色信息,法線信息,紋理坐標信息和索引信息等等。

       VAO在Graphics Card線性的存儲幾個對象信息,替代了以前發送我們需要的數據到Graphics Card上,這也是Direct3D沒有立即模式情況下工作的方法,這就意味著應用程序不需要傳輸數據到Graphics Card上而得到較高的性能。

 

Coding:

unsigned int vaoID[1]; // Our Vertex Array Object

 unsigned int vboID[1]; // Our Vertex Buffer Object

 

float* vertices = new float[18]; // Vertices for our square

 
 最后不能忘記

delete [] vertices; // Delete our vertices from memory

 

現在要填充頂點的數據值,把所有頂點的Z軸值設置為0,正方形的邊長為1,左上角(-0.5, 0.5, 0.0),右下角(0.5,-0.5, 0.0):

image

/** 
createSquare is used to create the Vertex Array Object which will hold our square. We will 
be hard coding in the vertices for the square, which will be done in this method. 
*/  
void OpenGLContext::createSquare(void) {  
float* vertices = new float[18];  // Vertices for our square  
  
vertices[0] = -0.5; vertices[1] = -0.5; vertices[2] = 0.0; // 左下  1
vertices[3] = -0.5; vertices[4] = 0.5; vertices[5] = 0.0;  // 左上  2 
vertices[6] = 0.5; vertices[7] = 0.5; vertices[8] = 0.0;   // 右上  3
  
vertices[9] = 0.5; vertices[10] = -0.5; vertices[11] = 0.0; // 右下 4 
vertices[12] = -0.5; vertices[13] = -0.5; vertices[14] = 0.0; //左下1
vertices[15] = 0.5; vertices[16] = 0.5; vertices[17] = 0.0; // 右上 3  
delete [] vertices; // Delete our vertices from memory  
}

    設置數據以后,我們需要用 glGenVertexArrays 創建一個Vertex Array Object, 然后使用glBindVertexArray綁定VAO,一旦VAO綁定后,使glGenBuffers 創建一個Vertex Buffer Object, 當然仍然需要使用glBindBuffer綁定VBO;

    順序如下:

    1. Generate Vertex Array Object
    2. Bind Vertex Array Object
    3. Generate Vertex Buffer Object
    4. Bind Vertex Buffer Object

   下面要使用glBufferData來初始化和用剛VAO創建的數據分配數據給VBO,再告訴VBO的數據是從VAO而來,需要清理Vertex Attributr Array和Vertex Array Object.

glGenVertexArrays(1, &vaoID[0]); // Create our Vertex Array Object  
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object so we can use it  
  
glGenBuffers(1, vboID); // Generate our Vertex Buffer Object  
glBindBuffer(GL_ARRAY_BUFFER, vboID[0]); // Bind our Vertex Buffer Object  
glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), vertices, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW  
  
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer  
  
glEnableVertexAttribArray(0); // Disable our Vertex Array Object  
glBindVertexArray(0); // Disable our Vertex Buffer Object  
  
delete [] vertices; // Delete our vertices from memory

繪制:

glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object  
  
glDrawArrays(GL_TRIANGLES, 0, 6); // Draw our square  
  
glBindVertexArray(0); // Unbind our Vertex Array Object

主要使用API:

void glGenVertexArrays(GLSize n, GLuint * *arrays);

返回n個當前未使用的名字,用作數組arrays中的頂點數組對象,

創建了VAO以后,需要初始化新的對象,并且把要使用的頂點數組數據的對象的集合與單個已分配的對象關聯起來,

GLvoid glBingVertexArray(GLuint array);

glBingVertexArray做了三件事,當使用的值array 不是零并且是從glGenVertexArrays()返回的值時,創建一個新的VAO,,并且分配該名字;當綁定到之前創建的一個VAO的時候,該VAO就是當前活動的;當綁定到一個為0的數組時,就停止使用VAO,并且返回頂點數組的默認狀態。

如果array不是之前從glGenVertexArray返回的值,如果是glDeleteVertexArray()已經釋放的值,如果調用任何一個gl*Pointer()函數來指定一個頂點數組,而在綁定一個非0VAO的時候,它沒有和緩沖區對象關聯起來,將會返回GL_INVALID_OPERATION錯誤。

這個函數是綁定VAO到上下文,并沒有像glBindBuffer那樣take a target。

void glVertexAttribPointer()

 首先要清楚關聯a buffer object和 a vertex attribute并不發生在glBindBuffer(GL_ARRAY_BUFFER),而是發生在glVertexAttribPointer();當你調用glVertexAttribPointer() ,OpenGL 獲取緩沖區綁定到GL_ARRAY_BUFFER 并且關聯頂點屬性,想象一下GL_ARRAY_BUFFER就像一個全局指針。

void glDrawArrays(GLenum type ,GLint start, GLint count);

ArrayDraw的方式:

void glDrawArrays(GLenum type, GLint start, GLint count)
{
    for(GLint element = start; element < start + count; element++)
    {
        VertexShader(positionAttribArray[element], colorAttribArray[element]);
    }
}

 

void glDrawElements(GLenum type, GLint count, GLenum type, GLsizeiptr indices)

Indexed Draw 的方式:

 

GLvoid *elementArray;

void glDrawElements(GLenum type, GLint count, GLenum type, GLsizeiptr indices)
{
    GLtype *ourElementArray = (type*)((GLbyte *)elementArray + indices);

    for(GLint elementIndex = 0; elementIndex < count; elementIndex++)
    {
        GLint element = ourElementArray[elementIndex];
        VertexShader(positionAttribArray[element], colorAttribArray[element]);
    }
}

假設頂點屬性是:
  Position Array:  Pos0, Pos1, Pos2, Pos3
  Color     Array:   Clr0,  Clr1,  Clr2,   Clr3

可以使用這些頂點數據以arraydraw的方式先繪制一個三角形,在繪制另外一個三角形(start=0,count=2),而如果使用index draw使用這個四個頂點能繪制4個三角行

   Element Array: 0, 1, 2,  0, 2, 3,  0, 3, 1,  1, 2, 3
即:
  (Pos0, Clr0), (Pos1, Clr1), (Pos2, Clr2),
  (Pos0, Clr0), (Pos2, Clr2), (Pos3, Clr3),
  (Pos0, Clr0), (Pos3, Clr3), (Pos1, Clr1),
  (Pos1, Clr1), (Pos2, Clr2), (Pos3, Clr3),

使用index draw需要準備兩件事:a properly constructed element array ,using a drawing command

Element arrays, 是存儲在buffer object:GL_ELEMENT_ARRAY_BUFFER 用法上是和GL_ARRAY_BUFFER一樣,但是必須要知道indexed drawing is only possible when a buffer object is bound to this binding point, and the element array comes from this buffer object.

so In order to do indexed drawing, we must bind the buffer to GL_ELEMENT_ARRAY_BUFFER and then call glDrawElements

void glDrawElements(GLenum mode,  GLsizei count,   GLenum type,  GLsizeiptr indices);

The first parameter is the same as the first parameter of glDrawArrays.

The count parameter defines how many indices will be pulled from the element array.

The type field defines what the basic type of the indices in the element array are. For example, if the indices are stored as 16-bit unsigned shorts (GLushort), then this field should be GL_UNSIGNED_SHORT. This allows the user the freedom to use whatever size of index they want.GL_UNSIGNED_BYTE and GL_UNSIGNED_INT (32-bit) are also allowed; indices must be unsigned.

The last parameter is the byte-offset into the element array at which the index data begins. Index data (and vertex data, for that matter) should always be aligned to its size. So if we are using 16-bit unsigned shorts for indices, then indices should be an even number.

有一個實例:

const int numberOfVertices = 36;

#define RIGHT_EXTENT 0.8f
#define LEFT_EXTENT -RIGHT_EXTENT
#define TOP_EXTENT 0.20f
#define MIDDLE_EXTENT 0.0f
#define BOTTOM_EXTENT -TOP_EXTENT
#define FRONT_EXTENT -1.25f
#define REAR_EXTENT -1.75f

#define GREEN_COLOR 0.75f, 0.75f, 1.0f, 1.0f
#define BLUE_COLOR     0.0f, 0.5f, 0.0f, 1.0f
#define RED_COLOR 1.0f, 0.0f, 0.0f, 1.0f
#define GREY_COLOR 0.8f, 0.8f, 0.8f, 1.0f
#define BROWN_COLOR 0.5f, 0.5f, 0.0f, 1.0f

const float vertexData[] = {
    //Object 1 positions
    LEFT_EXTENT,    TOP_EXTENT,        REAR_EXTENT,
    LEFT_EXTENT,    MIDDLE_EXTENT,    FRONT_EXTENT,
    RIGHT_EXTENT,    MIDDLE_EXTENT,    FRONT_EXTENT,
    RIGHT_EXTENT,    TOP_EXTENT,        REAR_EXTENT,

    LEFT_EXTENT,    BOTTOM_EXTENT,    REAR_EXTENT,
    LEFT_EXTENT,    MIDDLE_EXTENT,    FRONT_EXTENT,
    RIGHT_EXTENT,    MIDDLE_EXTENT,    FRONT_EXTENT,
    RIGHT_EXTENT,    BOTTOM_EXTENT,    REAR_EXTENT,

    LEFT_EXTENT,    TOP_EXTENT,        REAR_EXTENT,
    LEFT_EXTENT,    MIDDLE_EXTENT,    FRONT_EXTENT,
    LEFT_EXTENT,    BOTTOM_EXTENT,    REAR_EXTENT,

    RIGHT_EXTENT,    TOP_EXTENT,        REAR_EXTENT,
    RIGHT_EXTENT,    MIDDLE_EXTENT,    FRONT_EXTENT,
    RIGHT_EXTENT,    BOTTOM_EXTENT,    REAR_EXTENT,

    LEFT_EXTENT,    BOTTOM_EXTENT,    REAR_EXTENT,
    LEFT_EXTENT,    TOP_EXTENT,        REAR_EXTENT,
    RIGHT_EXTENT,    TOP_EXTENT,        REAR_EXTENT,
    RIGHT_EXTENT,    BOTTOM_EXTENT,    REAR_EXTENT,

    //Object 2 positions
    TOP_EXTENT,        RIGHT_EXTENT,    REAR_EXTENT,
    MIDDLE_EXTENT,    RIGHT_EXTENT,    FRONT_EXTENT,
    MIDDLE_EXTENT,    LEFT_EXTENT,    FRONT_EXTENT,
    TOP_EXTENT,        LEFT_EXTENT,    REAR_EXTENT,

    BOTTOM_EXTENT,    RIGHT_EXTENT,    REAR_EXTENT,
    MIDDLE_EXTENT,    RIGHT_EXTENT,    FRONT_EXTENT,
    MIDDLE_EXTENT,    LEFT_EXTENT,    FRONT_EXTENT,
    BOTTOM_EXTENT,    LEFT_EXTENT,    REAR_EXTENT,

    TOP_EXTENT,        RIGHT_EXTENT,    REAR_EXTENT,
    MIDDLE_EXTENT,    RIGHT_EXTENT,    FRONT_EXTENT,
    BOTTOM_EXTENT,    RIGHT_EXTENT,    REAR_EXTENT,
                    
    TOP_EXTENT,        LEFT_EXTENT,    REAR_EXTENT,
    MIDDLE_EXTENT,    LEFT_EXTENT,    FRONT_EXTENT,
    BOTTOM_EXTENT,    LEFT_EXTENT,    REAR_EXTENT,
                    
    BOTTOM_EXTENT,    RIGHT_EXTENT,    REAR_EXTENT,
    TOP_EXTENT,        RIGHT_EXTENT,    REAR_EXTENT,
    TOP_EXTENT,        LEFT_EXTENT,    REAR_EXTENT,
    BOTTOM_EXTENT,    LEFT_EXTENT,    REAR_EXTENT,

    //Object 1 colors
    GREEN_COLOR,
    GREEN_COLOR,
    GREEN_COLOR,
    GREEN_COLOR,

    BLUE_COLOR,
    BLUE_COLOR,
    BLUE_COLOR,
    BLUE_COLOR,

    RED_COLOR,
    RED_COLOR,
    RED_COLOR,

    GREY_COLOR,
    GREY_COLOR,
    GREY_COLOR,

    BROWN_COLOR,
    BROWN_COLOR,
    BROWN_COLOR,
    BROWN_COLOR,

    //Object 2 colors
    RED_COLOR,
    RED_COLOR,
    RED_COLOR,
    RED_COLOR,

    BROWN_COLOR,
    BROWN_COLOR,
    BROWN_COLOR,
    BROWN_COLOR,

    BLUE_COLOR,
    BLUE_COLOR,
    BLUE_COLOR,

    GREEN_COLOR,
    GREEN_COLOR,
    GREEN_COLOR,

    GREY_COLOR,
    GREY_COLOR,
    GREY_COLOR,
    GREY_COLOR,
};

const GLshort indexData[] =
{
    0, 2, 1,
    3, 2, 0,

    4, 5, 6,
    6, 7, 4,

    8, 9, 10,
    11, 13, 12,

    14, 16, 15,
    17, 16, 14,
};

GLuint vertexBufferObject;
GLuint indexBufferObject;

GLuint vaoObject1, vaoObject2;

 

void InitializeVertexBuffer()
{
    glGenBuffers(1, &vertexBufferObject);

    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenBuffers(1, &indexBufferObject);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

 

void InitializeVertexArrayObjects()
{
    glGenVertexArrays(1, &vaoObject1);
    glBindVertexArray(vaoObject1);

    size_t colorDataOffset = sizeof(float) * 3 * numberOfVertices;

    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)colorDataOffset);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);

    glBindVertexArray(0);

    glGenVertexArrays(1, &vaoObject2);
    glBindVertexArray(vaoObject2);

    size_t posDataOffset = sizeof(float) * 3 * (numberOfVertices/2);
    colorDataOffset += sizeof(float) * 4 * (numberOfVertices/2);

    //Use the same buffer object previously bound to GL_ARRAY_BUFFER.
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)posDataOffset);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)colorDataOffset);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);

    glBindVertexArray(0);
}

 

Draw:

    glBindVertexArray(vaoObject1);
    glUniform3f(offsetUniform, 0.0f, 0.0f, 0.0f);
    glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);

    glBindVertexArray(vaoObject2);
    glUniform3f(offsetUniform, 0.0f, 0.0f, -1.0f);
    glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);

    glBindVertexArray(0);

例子:

#include <stdlib.h>
#include <stdio.h>
/* Ensure we are using opengl's core profile only */
#define GL3_PROTOTYPES 1
#include <GL3/gl3.h>
 
#include <SDL.h>
 
#define PROGRAM_NAME "Tutorial2"
 
/* A simple function that will read a file into an allocated char pointer buffer */
char* filetobuf(char *file)
{
    FILE *fptr;
    long length;
    char *buf;
 
    fptr = fopen(file, "rb"); /* Open file for reading */
    if (!fptr) /* Return NULL on failure */
        return NULL;
    fseek(fptr, 0, SEEK_END); /* Seek to the end of the file */
    length = ftell(fptr); /* Find out how many bytes into the file we are */
    buf = (char*)malloc(length+1); /* Allocate a buffer for the entire length of the file and a null terminator */
    fseek(fptr, 0, SEEK_SET); /* Go back to the beginning of the file */
    fread(buf, length, 1, fptr); /* Read the contents of the file in to the buffer */
    fclose(fptr); /* Close the file */
    buf[length] = 0; /* Null terminator */
 
    return buf; /* Return the buffer */
}
 
/* A simple function that prints a message, the error code returned by SDL, and quits the application */
void sdldie(char *msg)
{
    printf("%s: %s\n", msg, SDL_GetError());
    SDL_Quit();
    exit(1);
}
 
void setupwindow(SDL_WindowID *window, SDL_GLContext *context)
{
    if (SDL_Init(SDL_INIT_VIDEO) < 0) /* Initialize SDL's Video subsystem */
        sdldie("Unable to initialize SDL"); /* Or die on error */
 
    /* Request an opengl 3.2 context.
     * SDL doesn't have the ability to choose which profile at this time of writing,
     * but it should default to the core profile */
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
 
    /* Turn on double buffering with a 24bit Z buffer.
     * You may need to change this to 16 or 32 for your system */
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
 
    /* Create our window centered at 512x512 resolution */
    *window = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
    if (!*window) /* Die if creation failed */
        sdldie("Unable to create window");
 
    /* Create our opengl context and attach it to our window */
    *context = SDL_GL_CreateContext(*window);
 
    /* This makes our buffer swap syncronized with the monitor's vertical refresh */
    SDL_GL_SetSwapInterval(1);
}
 
void drawscene(SDL_WindowID window)
{
    int i; /* Simple iterator */
    GLuint vao, vbo[2]; /* Create handles for our Vertex Array Object and two Vertex Buffer Objects */
    int IsCompiled_VS, IsCompiled_FS;
    int IsLinked;
    int maxLength;
    char *vertexInfoLog;
    char *fragmentInfoLog;
    char *shaderProgramInfoLog;
 
    /* We're going to create a simple diamond made from lines */
    const GLfloat diamond[4][2] = {
    {  0.0,  1.0  }, /* Top point */           |
    {  1.0,  0.0  }, /* Right point */         | 
    {  0.0, -1.0  }, /* Bottom point */
    { -1.0,  0.0  } }; /* Left point */
 
    const GLfloat colors[4][3] = {
    {  1.0,  0.0,  0.0  }, /* Red */
    {  0.0,  1.0,  0.0  }, /* Green */
    {  0.0,  0.0,  1.0  }, /* Blue */
    {  1.0,  1.0,  1.0  } }; /* White */
 
    /* These pointers will receive the contents of our shader source code files */
    GLchar *vertexsource, *fragmentsource;
 
    /* These are handles used to reference the shaders */
    GLuint vertexshader, fragmentshader;
 
    /* This is a handle to the shader program */
    GLuint shaderprogram;
 
    /* Allocate and assign a Vertex Array Object to our handle */
    glGenVertexArrays(1, &vao);
 
    /* Bind our Vertex Array Object as the current used object */
    glBindVertexArray(vao);
 
    /* Allocate and assign two Vertex Buffer Objects to our handle */
    glGenBuffers(2, vbo);
 
    /* Bind our first VBO as being the active buffer and storing vertex attributes (coordinates) */
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
 
    /* Copy the vertex data from diamond to our buffer */
    /* 8 * sizeof(GLfloat) is the size of the diamond array, since it contains 8 GLfloat values */
    glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), diamond, GL_STATIC_DRAW);
 
    /* Specify that our coordinate data is going into attribute index 0, and contains two floats per vertex */
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
 
    /* Enable attribute index 0 as being used */
    glEnableVertexAttribArray(0);
 
    /* Bind our second VBO as being the active buffer and storing vertex attributes (colors) */
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
 
    /* Copy the color data from colors to our buffer */
    /* 12 * sizeof(GLfloat) is the size of the colors array, since it contains 12 GLfloat values */
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), colors, GL_STATIC_DRAW);
 
    /* Specify that our color data is going into attribute index 1, and contains three floats per vertex */
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
 
    /* Enable attribute index 1 as being used */
    glEnableVertexAttribArray(1);
 
    /* Read our shaders into the appropriate buffers */
    vertexsource = filetobuf("tutorial2.vert");
    fragmentsource = filetobuf("tutorial2.frag");
 
    /* Create an empty vertex shader handle */
    vertexshader = glCreateShader(GL_VERTEX_SHADER);
 
    /* Send the vertex shader source code to GL */
    /* Note that the source code is NULL character terminated. */
    /* GL will automatically detect that therefore the length info can be 0 in this case (the last parameter) */
    glShaderSource(vertexshader, 1, (const GLchar**)&vertexsource, 0);
 
    /* Compile the vertex shader */
    glCompileShader(vertexshader);
 
    glGetShaderiv(vertexshader, GL_COMPILE_STATUS, &IsCompiled_VS);
    if(IsCompiled_VS == FALSE)
    {
       glGetShaderiv(vertexshader, GL_INFO_LOG_LENGTH, &maxLength);
 
       /* The maxLength includes the NULL character */
       vertexInfoLog = (char *)malloc(maxLength);
 
       glGetShaderInfoLog(vertexshader, maxLength, &maxLength, vertexInfoLog);
 
       /* Handle the error in an appropriate way such as displaying a message or writing to a log file. */
       /* In this simple program, we'll just leave */
       free(vertexInfoLog);
       return;
    }
 
    /* Create an empty fragment shader handle */
    fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
 
    /* Send the fragment shader source code to GL */
    /* Note that the source code is NULL character terminated. */
    /* GL will automatically detect that therefore the length info can be 0 in this case (the last parameter) */
    glShaderSource(fragmentshader, 1, (const GLchar**)&fragmentsource, 0);
 
    /* Compile the fragment shader */
    glCompileShader(fragmentshader);
 
    glGetShaderiv(fragmentshader, GL_COMPILE_STATUS, &IsCompiled_FS);
    if(IsCompiled_FS == FALSE)
    {
       glGetShaderiv(fragmentshader, GL_INFO_LOG_LENGTH, &maxLength);
 
       /* The maxLength includes the NULL character */
       fragmentInfoLog = (char *)malloc(maxLength);
 
       glGetShaderInfoLog(fragmentshader, maxLength, &maxLength, fragmentInfoLog);
 
       /* Handle the error in an appropriate way such as displaying a message or writing to a log file. */
       /* In this simple program, we'll just leave */
       free(fragmentInfoLog);
       return;
    }
 
    /* If we reached this point it means the vertex and fragment shaders compiled and are syntax error free. */
    /* We must link them together to make a GL shader program */
    /* GL shader programs are monolithic. It is a single piece made of 1 vertex shader and 1 fragment shader. */
    /* Assign our program handle a "name" */
    shaderprogram = glCreateProgram();
 
    /* Attach our shaders to our program */
    glAttachShader(shaderprogram, vertexshader);
    glAttachShader(shaderprogram, fragmentshader);
 
    /* Bind attribute index 0 (coordinates) to in_Position and attribute index 1 (color) to in_Color */
    /* Attribute locations must be setup before calling glLinkProgram. */
    glBindAttribLocation(shaderprogram, 0, "in_Position");
    glBindAttribLocation(shaderprogram, 1, "in_Color");
 
    /* Link our program */
    /* At this stage, the vertex and fragment programs are inspected, optimized and a binary code is generated for the shader. */
    /* The binary code is uploaded to the GPU, if there is no error. */
    glLinkProgram(shaderprogram);
 
    /* Again, we must check and make sure that it linked. If it fails, it would mean either there is a mismatch between the vertex */
    /* and fragment shaders. It might be that you have surpassed your GPU's abilities. Perhaps too many ALU operations or */
    /* too many texel fetch instructions or too many interpolators or dynamic loops. */
 
    glGetProgramiv(shaderprogram, GL_LINK_STATUS, (int *)&IsLinked);
    if(IsLinked == FALSE)
    {
       /* Noticed that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. */
       glGetProgramiv(shaderprogram, GL_INFO_LOG_LENGTH, &maxLength);
 
       /* The maxLength includes the NULL character */
       shaderProgramInfoLog = (char *)malloc(maxLength);
 
       /* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */
       glGetProgramInfoLog(shaderprogram, maxLength, &maxLength, shaderProgramInfoLog);
 
       /* Handle the error in an appropriate way such as displaying a message or writing to a log file. */
       /* In this simple program, we'll just leave */
       free(shaderProgramInfoLog);
       return;
    }
 
    /* Load the shader into the rendering pipeline */
    glUseProgram(shaderprogram);
 
    /* Loop our display increasing the number of shown vertexes each time.
     * Start with 2 vertexes (a line) and increase to 3 (a triangle) and 4 (a diamond) */
    for (i=2; i <= 4; i++)
    {
        /* Make our background black */
        glClearColor(0.0, 0.0, 0.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
 
        /* Invoke glDrawArrays telling that our data is a line loop and we want to draw 2-4 vertexes */
        glDrawArrays(GL_LINE_LOOP, 0, i);
 
        /* Swap our buffers to make our changes visible */
        SDL_GL_SwapWindow(window);
 
        /* Sleep for 2 seconds */
        SDL_Delay(2000);
    }
 
    /* Cleanup all the things we bound and allocated */
    glUseProgram(0);
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDetachShader(shaderprogram, vertexshader);
    glDetachShader(shaderprogram, fragmentshader);
    glDeleteProgram(shaderprogram);
    glDeleteShader(vertexshader);
    glDeleteShader(fragmentshader);
    glDeleteBuffers(2, vbo);
    glDeleteVertexArrays(1, &vao);
    free(vertexsource);
    free(fragmentsource);
}
 
void destroywindow(SDL_WindowID window, SDL_GLContext context)
{
    SDL_GL_DeleteContext(context);
    SDL_DestroyWindow(window);
    SDL_Quit();
}
 
/* Our program's entry point */
int main(int argc, char *argv[])
{
    SDL_WindowID mainwindow; /* Our window handle */
    SDL_GLContext maincontext; /* Our opengl context handle */
 
    /* Create our window, opengl context, etc... */
    setupwindow(&mainwindow, &maincontext);
 
    /* Call our function that performs opengl operations */
    drawscene(mainwindow);
 
    /* Delete our opengl context, destroy our window, and shutdown SDL */
    destroywindow(mainwindow, maincontext);
 
    return 0;
}

參考:

VAOs,_VBOs,_Vertex_and_Fragment_Shaders

VAO

opengl-3-3-glsl-1-5-sample

Vertex array object

Open GL : Using Vertex Array Objects to Organize Your Buffers

Vertex Buffer Objects

posted on 2012-02-21 17:42 情絕格調(fresmaster) 閱讀(17349) 評論(0)  編輯 收藏 引用 所屬分類: Graphics
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            最新国产拍偷乱拍精品| 樱桃国产成人精品视频| 一区二区三区四区五区精品视频 | 亚洲欧美国产日韩天堂区| 亚洲精品一区二区三区福利| 欧美国产乱视频| 日韩视频免费观看| 一本色道久久精品| 国产视频一区欧美| 麻豆久久精品| 欧美日韩高清在线观看| 亚洲视频精品在线| 亚洲影音一区| 亚洲国产成人一区| 亚洲精品美女久久久久| 欧美特黄一级大片| 久久精品在线免费观看| 美女国内精品自产拍在线播放| 亚洲精品欧美日韩专区| 在线视频免费在线观看一区二区| 国产欧美精品| 欧美激情在线免费观看| 欧美视频在线观看免费网址| 欧美一区1区三区3区公司| 久久精品女人的天堂av| 亚洲精品在线二区| 亚洲欧美国产高清| 亚洲激情啪啪| 亚洲免费在线观看| 在线看成人片| 亚洲深夜福利| 在线成人免费视频| 亚洲午夜一区二区| 亚洲国产成人在线播放| 亚洲综合精品一区二区| 亚洲丰满少妇videoshd| 亚洲一区bb| 亚洲美女区一区| 欧美中文字幕在线观看| 一区二区三区四区在线| 久久九九免费| 午夜亚洲一区| 欧美精品激情在线观看| 久久人人97超碰国产公开结果 | 欧美激情精品久久久久久变态| 亚洲女同精品视频| 欧美电影免费| 另类天堂av| 国产一区二区三区四区五区美女| 91久久久久| 亚洲国产综合视频在线观看| 亚洲欧美日韩一区二区在线 | 欧美专区日韩专区| 欧美日韩精品一区二区| 欧美va天堂在线| 精品成人在线视频| 性色av一区二区三区在线观看| 日韩视频免费观看高清完整版| 久久久久久亚洲精品不卡4k岛国| 亚洲欧美另类在线观看| 欧美日韩亚洲系列| 亚洲国产欧美一区| 亚洲激情av| 美女精品在线观看| 欧美国产三级| 亚洲精品日日夜夜| 蜜臀av性久久久久蜜臀aⅴ| 欧美.com| 亚洲电影第三页| 免费看亚洲片| 欧美激情第五页| 亚洲精品一区二区三区樱花| 卡通动漫国产精品| 亚洲第一精品夜夜躁人人爽| 亚洲国产欧美在线| 欧美电影免费观看高清完整版| 亚洲福利国产| 日韩亚洲欧美成人| 欧美日韩一区在线播放| 一区二区三区四区蜜桃| 午夜精品福利一区二区三区av| 欧美亚男人的天堂| 午夜亚洲精品| 久久深夜福利| 亚洲三级免费| 欧美亚男人的天堂| 校园激情久久| 欧美福利视频一区| 亚洲伦理在线免费看| 欧美日韩在线视频一区二区| 中文国产一区| 久久激情一区| 亚洲国产精品一区制服丝袜| 欧美韩日高清| 亚洲视频二区| 久久婷婷蜜乳一本欲蜜臀| 亚洲欧洲精品天堂一级| 欧美区日韩区| 亚洲欧美日韩综合| 亚洲第一黄色| 亚洲欧美综合v| 在线看欧美日韩| 国产精品va| 麻豆成人综合网| 在线一区亚洲| 欧美国产亚洲另类动漫| 亚洲一区久久| 亚洲高清免费| 国产麻豆午夜三级精品| 葵司免费一区二区三区四区五区| 亚洲精品久久久蜜桃| 久久国产精品99国产精| 亚洲黑丝在线| 国产一区二区三区高清| 欧美电影免费观看高清| 欧美一区影院| 99热免费精品在线观看| 欧美成人综合在线| 久久精品国产77777蜜臀 | 国产精品扒开腿爽爽爽视频 | 亚洲一区二区高清| 欧美激情一区二区三区四区 | 野花国产精品入口| 合欧美一区二区三区| 欧美日本一区二区视频在线观看| 欧美一区激情| 一区二区三区导航| 亚洲福利小视频| 嫩草成人www欧美| 久久成人国产| 亚洲欧美日本伦理| 一本一道久久综合狠狠老精东影业| 国产一区二三区| 国产精品美女主播在线观看纯欲| 欧美成人午夜免费视在线看片| 先锋影院在线亚洲| 中日韩美女免费视频网站在线观看| 亚洲国产精品成人久久综合一区| 久久亚洲视频| 久久蜜桃av一区精品变态类天堂| 亚洲欧美中文另类| 亚洲主播在线播放| 亚洲一区精品视频| 亚洲婷婷综合久久一本伊一区| 亚洲精品偷拍| 一区二区日韩伦理片| 亚洲美女免费视频| 日韩视频免费观看| 亚洲乱码国产乱码精品精98午夜| 国内精品久久久久久| 国产精品一区久久| 国产精品一区二区你懂的| 国产精品丝袜久久久久久app| 国产精品av免费在线观看| 欧美日韩在线高清| 欧美视频在线播放| 国产精品女同互慰在线看| 国产精品免费福利| 国产伦精品一区二区三区高清版| 国产目拍亚洲精品99久久精品 | 免费在线亚洲| 欧美精品免费在线| 国产精品裸体一区二区三区| 欧美三级日本三级少妇99| 欧美午夜久久久| 国产精品入口尤物| 国产一区自拍视频| 亚洲欧洲精品一区| 亚洲天堂成人在线视频| 欧美一区二区三区在线视频| 久久国产日韩欧美| 欧美96在线丨欧| 一本色道久久88综合日韩精品| 亚洲欧美精品在线观看| 久久精品青青大伊人av| 免费黄网站欧美| 国产精品大全| 在线免费观看日本欧美| 一区二区三区www| 久久精品二区| 亚洲国产精选| 午夜精品一区二区三区在线| 久久久无码精品亚洲日韩按摩| 欧美电影在线播放| 国产精品视频yy9099| **网站欧美大片在线观看| 亚洲天堂av图片| 美日韩免费视频| 亚洲午夜激情免费视频| 另类人畜视频在线| 国产精品看片你懂得| 亚洲精品久久久久久久久久久| 一区二区三区产品免费精品久久75| 久久狠狠婷婷| 夜夜嗨av一区二区三区中文字幕| 久久久久久有精品国产| 国产精品亚洲第一区在线暖暖韩国| 亚洲国产成人午夜在线一区| 午夜亚洲福利在线老司机| 欧美激情在线狂野欧美精品|