OpenGL进阶(九) - GLSL中VAO和VBO的使用

来源:互联网 发布:python中文网站 编辑:程序博客网 时间:2024/05/16 17:26

Vertex Shader : 基于GLSL的语法写的一种类C的代码,可以用来控制顶点的特性,比如位置,颜色还有纹理坐标等。

Fragment Shader:用于计算每个片段的颜色,可用于实现光照还有真实感的贴图。

还有一种Shader 叫做Geometry Shader,用于添加顶点。

使用结合了GLSL的OpenGL程序的渲染管线就变成了这样:





VAO和VBO

VBO: 显卡存储空间里的一块缓存区(Buffer),用于记录顶点的信息,包括法线,问路坐标等,这个Buffer有它的名字(VBO的ID),OpenGL在GPU的某处记录着这个ID和对应的显存地址(或者地址偏移,类似内存)。

VAO:是一个对象,其中包含一个或者更多的Vertex Buffer Objects,用于记录渲染对象的完整信息。

使用步骤如下:

1.生成VAO

void glGenVertexArrays( GLsizei n,GLuint *arrays);

- generate vertex array object names

Parameters
n:指定要生成VAO的数量

arrays:指定VAO名字生成的位置


2.绑定VAO

void glBindVertexArray(GLuint array);

- generate vertex array object names

Parameters
array:执行要绑定的数组


3.产生VBOs

void glGenBuffers( GLsizei n,GLuint * buffers);
- generate buffer object names


Parameters
n:生成VBO的名字的个数
buffers:生成VBO名字的位置

4.绑定VBOS

void glBindBuffer( GLenum target, GLuint buffer);
- bind a named buffer object

Parameters
target
Specifies the target to which the buffer object is bound. 


buffer
Specifies the name of a buffer object.

5.给VBO分配数据

void glBufferData( GLenum target,GLsizeiptr size,const GLvoid * data,GLenum usage);
creates and initializes a buffer object's data store.

Parameters
target
Specifies the target buffer object. 

size
Specifies the size in bytes of the buffer object's new data store.

data
Specifies a pointer to data that will be copied into the data store for initialization, or NULL if no data is to be copied.

usage
Specifies the expected usage pattern of the data store.

6.给对应的顶点属性数组指定数据

void glVertexAttribPointer( GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid * pointer);

-  define an array of generic vertex attribute data

Parameters

index
Specifies the index of the generic vertex attribute to be modified.

size
Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, 4. Additionally, the symbolic constant GL_BGRA is accepted by glVertexAttribPointer. The initial value is 4.

type
Specifies the data type of each component in the array. The symbolic constants GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, and GL_UNSIGNED_INT are accepted by glVertexAttribPointer and glVertexAttribIPointer. Additionally GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, GL_FIXED, GL_INT_2_10_10_10_REV, GL_UNSIGNED_INT_2_10_10_10_REV and GL_UNSIGNED_INT_10F_11F_11F_REV are accepted by glVertexAttribPointer. GL_DOUBLE is also accepted by glVertexAttribLPointer and is the only token accepted by the type parameter for that function. The initial value is GL_FLOAT.

normalized
For glVertexAttribPointer, specifies whether fixed-point data values should be normalized (GL_TRUE) or converted directly as fixed-point values (GL_FALSE) when they are accessed.

stride
Specifies the byte offset between consecutive generic vertex attributes. If stride is 0, the generic vertex attributes are understood to be tightly packed in the array. The initial value is 0.

pointer
Specifies a offset of the first component of the first generic vertex attribute in the array in the data store of the buffer currently bound to the GL_ARRAY_BUFFER target. The initial value is 0.

7.设置Attribute变量,传递给shader

void glBindAttribLocation( GLuint program,GLuint index,const GLchar *name);
-Associates a generic vertex attribute index with a named attribute variable

Parameters

program
Specifies the handle of the program object in which the association is to be made.

index
Specifies the index of the generic vertex attribute to be bound.

name
Specifies a null terminated string containing the name of the vertex shader attribute variable to which index is to be bound.



利用VAO、VBO绘制图形

下面是一个绘制的实例。

basic.vert

[cpp] view plaincopyprint?
  1. #version 400  
  2. // in_Position was bound to attribute index 0 and in_Color was bound to attribute index 1  
  3. in  vec2 in_Position;  
  4. in  vec3 in_Color;  
  5.    
  6. // We output the ex_Color variable to the next shader in the chain  
  7. out vec3 ex_Color;  
  8. void main(void) {  
  9.     // Since we are using flat lines, our input only had two points: x and y.  
  10.     // Set the Z coordinate to 0 and W coordinate to 1  
  11.    
  12.     gl_Position = vec4(in_Position.x, in_Position.y, 0.0, 1.0);  
  13.    
  14.     // GLSL allows shorthand use of vectors too, the following is also valid:  
  15.     // gl_Position = vec4(in_Position, 0.0, 1.0);  
  16.     // We're simply passing the color through unmodified  
  17.    
  18.     ex_Color = in_Color;  
  19. }  
#version 400// in_Position was bound to attribute index 0 and in_Color was bound to attribute index 1in  vec2 in_Position;in  vec3 in_Color; // We output the ex_Color variable to the next shader in the chainout vec3 ex_Color;void main(void) {    // Since we are using flat lines, our input only had two points: x and y.    // Set the Z coordinate to 0 and W coordinate to 1     gl_Position = vec4(in_Position.x, in_Position.y, 0.0, 1.0);     // GLSL allows shorthand use of vectors too, the following is also valid:    // gl_Position = vec4(in_Position, 0.0, 1.0);    // We're simply passing the color through unmodified     ex_Color = in_Color;}


basic.frag
[cpp] view plaincopyprint?
  1. #version 400  
  2. precision highp float;  
  3.    
  4. in  vec3 ex_Color;  
  5. out vec4 gl_FragColor;  
  6.    
  7. void main(void) {  
  8.     // Pass through our original color with full opacity.  
  9.     gl_FragColor = vec4(ex_Color,1.0);  
  10. }  
#version 400precision highp float; in  vec3 ex_Color;out vec4 gl_FragColor; void main(void) {    // Pass through our original color with full opacity.    gl_FragColor = vec4(ex_Color,1.0);}

main.c

[cpp] view plaincopyprint?
  1. /***************************************************************************** 
  2. Copyright: 2013, ustc All rights reserved. 
  3. contact:k283228391@126.com 
  4. File name: main.c 
  5. Description:Using VAO and VBO in opengl. 
  6. Author:Silang Quan 
  7. Version: 1.0 
  8. Date: 2013.8.1 
  9. *****************************************************************************/  
  10. #include <SDL/SDL.h>  
  11. #include <GL/glew.h>  
  12. #include <GL/gl.h>  
  13. #include <GL/glu.h>  
  14. #include <stdio.h>  
  15. #include <stdlib.h>  
  16.   
  17.   
  18. const int SCREEN_WIDTH = 800;  
  19. const int SCREEN_HEIGHT =800;  
  20. const int SCREEN_BPP = 32;  
  21. SDL_Surface *screen;  
  22. //Whether the window is windowed or not  
  23. bool windowed;  
  24. //Whether the window is fine  
  25. bool windowOK;  
  26. //Handler for GLSL program  
  27. GLuint programHandle;  
  28. GLuint vShader;  
  29. GLuint fShader;  
  30. GLuint vao, vbo[2];  
  31.   
  32. void quit( int code )  
  33. {  
  34.     SDL_Quit( );  
  35.     /* Exit program. */  
  36.     exit( code );  
  37. }  
  38.   
  39. char *textFileRead(char *fn) {  
  40.    
  41.     FILE *fp;  
  42.     char *content = NULL;  
  43.    
  44.     int count=0;  
  45.    
  46.     if (fn != NULL) {  
  47.         fp = fopen(fn,"rt");  
  48.    
  49.         if (fp != NULL) {  
  50.    
  51.       fseek(fp, 0, SEEK_END);  
  52.       count = ftell(fp);  
  53.       rewind(fp);  
  54.    
  55.             if (count > 0) {  
  56.                 content = (char *)malloc(sizeof(char) * (count+1));  
  57.                 count = fread(content,sizeof(char),count,fp);  
  58.                 content[count] = '\0';  
  59.             }  
  60.             fclose(fp);  
  61.         }  
  62.     }  
  63.     return content;  
  64. }  
  65.   
  66. void toggle_fullscreen()  
  67. {  
  68.     //If the screen is windowed  
  69.     if( windowed == true )  
  70.     {  
  71.         //Set the screen to fullscreen  
  72.         screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE| SDL_FULLSCREEN );  
  73.   
  74.         //If there's an error  
  75.         if( screen == NULL )  
  76.         {  
  77.             windowOK = false;  
  78.             return;  
  79.         }  
  80.   
  81.         //Set the window state flag  
  82.         windowed = false;  
  83.     }  
  84.     //If the screen is fullscreen  
  85.     else if( windowed == false )  
  86.     {  
  87.         //Window the screen  
  88.         screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE );  
  89.   
  90.         //If there's an error  
  91.         if( screen == NULL )  
  92.         {  
  93.             windowOK = false;  
  94.             return;  
  95.         }  
  96.   
  97.         //Set the window state flag  
  98.         windowed = true;  
  99.     }  
  100. }  
  101.   
  102. void handleKeyEvent( SDL_keysym* keysym )  
  103. {  
  104.     switch( keysym->sym )  
  105.     {  
  106.     case SDLK_ESCAPE:  
  107.         quit( 0 );  
  108.         break;  
  109.     case SDLK_SPACE:  
  110.         break;  
  111.     case SDLK_F1:  
  112.         toggle_fullscreen();  
  113.         break;  
  114.     default:  
  115.         break;  
  116.     }  
  117. }  
  118.   
  119. void resizeGL(int width,int height)  
  120. {  
  121.     if ( height == 0 )  
  122.     {  
  123.         height = 1;  
  124.     }  
  125.     //Reset View  
  126.     glViewport( 0, 0, (GLint)width, (GLint)height );  
  127.     //Choose the Matrix mode  
  128.     glMatrixMode( GL_PROJECTION );  
  129.     //reset projection  
  130.     glLoadIdentity();  
  131.     //set perspection  
  132.     gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );  
  133.     //choose Matrix mode  
  134.     glMatrixMode( GL_MODELVIEW );  
  135.     glLoadIdentity();  
  136. }  
  137.   
  138. void handleEvents()  
  139. {  
  140.     // Our SDL event placeholder.  
  141.     SDL_Event event;  
  142.     //Grab all the events off the queue.  
  143.     while( SDL_PollEvent( &event ) ) {  
  144.         switch( event.type ) {  
  145.         case SDL_KEYDOWN:  
  146.             // Handle key Event  
  147.             handleKeyEvent( &event.key.keysym );  
  148.             break;  
  149.         case SDL_QUIT:  
  150.             // Handle quit requests (like Ctrl-c).  
  151.             quit( 0 );  
  152.             break;  
  153.         case SDL_VIDEORESIZE:  
  154.             //Handle resize event  
  155.             screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 16,  
  156.                                       SDL_OPENGL|SDL_RESIZABLE);  
  157.             if ( screen )  
  158.             {  
  159.                 resizeGL(screen->w, screen->h);  
  160.             }  
  161.             break;  
  162.         }  
  163.     }  
  164. }  
  165.   
  166. void initSDL(int width,int height,int bpp,int flags)  
  167. {  
  168.     // First, initialize SDL's video subsystem.  
  169.     if( SDL_Init( SDL_INIT_VIDEO ) < 0 )  
  170.     {  
  171.         fprintf( stderr, "Video initialization failed: %s\n",  
  172.                  SDL_GetError( ) );  
  173.         quit( 1 );  
  174.     }  
  175.     atexit(SDL_Quit);  
  176.     //Set some Attribute of OpenGL in SDL  
  177.     SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );  
  178.     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );  
  179.     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );  
  180.     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );  
  181.     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );  
  182.   
  183.     //Set the video mode  
  184.     screen= SDL_SetVideoMode( width, height, bpp,flags);  
  185.     if(!screen )  
  186.     {  
  187.         fprintf( stderr, "Video mode set failed: %s\n",SDL_GetError( ) );  
  188.         quit( 1 );  
  189.     windowed=false;  
  190.     }  
  191.     else windowed=true;  
  192.     resizeGL(screen->w, screen->h);  
  193.     //Set caption  
  194.     SDL_WM_SetCaption( "OpenGL Shading Language Test", NULL );  
  195.       
  196.   
  197. }  
  198.   
  199. void initShader()  
  200. {  
  201. //Init VAO and VBO  
  202.   
  203.  /* We're going to create a simple diamond made from lines */  
  204.   
  205.     const GLfloat diamond[4][2] = {  
  206.     {  0.0,  1.0  }, /* Top point */  
  207.     {  1.0,  0.0  }, /* Right point */  
  208.     {  0.0, -1.0  }, /* Bottom point */  
  209.     { -1.0,  0.0  } }; /* Left point */  
  210.    
  211.     const GLfloat colors[4][3] = {  
  212.     {  1.0,  0.0,  0.0  }, /* Red */  
  213.     {  0.0,  1.0,  0.0  }, /* Green */  
  214.     {  0.0,  0.0,  1.0  }, /* Blue */  
  215.     {  1.0,  1.0,  1.0  } }; /* White */  
  216.    
  217.     /* These pointers will receive the contents of our shader source code files */  
  218.     GLchar *vertexsource, *fragmentsource;  
  219.    
  220.     /* These are handles used to reference the shaders */  
  221.     GLuint vertexshader, fragmentshader;  
  222.    
  223.     /* This is a handle to the shader program */  
  224.     GLuint shaderprogram;  
  225.       
  226.      /* Allocate and assign a Vertex Array Object to our handle */  
  227.     glGenVertexArrays(1, &vao);  
  228.    
  229.     /* Bind our Vertex Array Object as the current used object */  
  230.     glBindVertexArray(vao);  
  231.    
  232.     /* Allocate and assign two Vertex Buffer Objects to our handle */  
  233.     glGenBuffers(2, vbo);  
  234.    
  235.     /* Bind our first VBO as being the active buffer and storing vertex attributes (coordinates) */  
  236.     glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);  
  237.       
  238.     glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), diamond, GL_STATIC_DRAW);  
  239.       
  240.       /* Specify that our coordinate data is going into attribute index 0, and contains two floats per vertex */  
  241.     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);  
  242.    
  243.     /* Enable attribute index 0 as being used */  
  244.     glEnableVertexAttribArray(0);  
  245.    
  246.     /* Bind our second VBO as being the active buffer and storing vertex attributes (colors) */  
  247.     glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);  
  248.       
  249.     glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), colors, GL_STATIC_DRAW);  
  250.    
  251.     /* Specify that our color data is going into attribute index 1, and contains three floats per vertex */  
  252.     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);  
  253.    
  254.     /* Enable attribute index 1 as being used */  
  255.     glEnableVertexAttribArray(1);  
  256.       
  257.     vShader = glCreateShader( GL_VERTEX_SHADER );  
  258.     fShader = glCreateShader( GL_FRAGMENT_SHADER );  
  259.     printf("Here\n");  
  260.     if(0 == vShader || 0 == fShader)  
  261.     {  
  262.         fprintf(stderr, "Error creating vertex shader.\n");  
  263.         quit(1);  
  264.     }  
  265.       
  266.     GLchar* vShaderCode = textFileRead("basic.vert");  
  267.     GLchar* fShaderCode = textFileRead("basic.frag");  
  268.     const GLchar* vCodeArray[1] = {vShaderCode};  
  269.     const GLchar* fCodeArray[1] = {fShaderCode};  
  270.     glShaderSource(vShader, 1, vCodeArray, NULL);  
  271.     glShaderSource(fShader, 1, fCodeArray, NULL);  
  272.       
  273.     glCompileShader(vShader);  
  274.     glCompileShader(fShader);  
  275.     free(vShaderCode);  
  276.     free(fShaderCode);  
  277.     //const GLchar* codeArray[] = {shaderCode};  
  278.     //Check the compile result  
  279.     GLint logLen;  
  280.     glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &logLen);  
  281.     if(logLen > 0)  
  282.     {  
  283.         char *log = (char *)malloc(logLen);  
  284.         GLsizei written;  
  285.         glGetShaderInfoLog(vShader, logLen, &written, log);  
  286.         printf("Shader compile error log: %s\n",log);  
  287.         free(log);  
  288.     }  
  289.       
  290.     programHandle = glCreateProgram();  
  291.     if(0 == programHandle)  
  292.     {  
  293.         fprintf(stderr, "Error creating programHandle.\n");  
  294.         quit(1);  
  295.     }  
  296.       
  297.     glAttachShader(programHandle, vShader);  
  298.     glAttachShader(programHandle, fShader);  
  299.       
  300.       
  301.     glBindAttribLocation(programHandle, 0, "in_Position");  
  302.     glBindAttribLocation(programHandle, 1, "in_Color");  
  303.       
  304.     glLinkProgram(programHandle);  
  305.     //glUseProgram(programHandle);  
  306. }  
  307.   
  308. void freeShader()  
  309. {  
  310.     glDisableVertexAttribArray(0);  
  311.     glDisableVertexAttribArray(1);  
  312.     glDetachShader(programHandle, fShader);  
  313.     glDetachShader(programHandle, vShader);  
  314.     //glDeteteProgram(programHandle);  
  315.     glDeleteShader(fShader);  
  316.     glDeleteShader(vShader);  
  317.     glDeleteBuffers(2, vbo);  
  318.     glDeleteVertexArrays(1, &vao);  
  319. }  
  320. void renderGL()  
  321. {  
  322.     /* These are to calculate our fps */  
  323.     static GLint T0     = 0;  
  324.     static GLint Frames = 0;  
  325.     // Clear the color and depth buffers.  
  326.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );  
  327.     // We don't want to modify the projection matrix. */  
  328.     glMatrixMode( GL_MODELVIEW );  
  329.     glLoadIdentity( );  
  330.     // Move down the z-axis.  
  331.     glTranslatef( 0.0, 0.0, -5.0 );  
  332.     
  333.    
  334.       
  335.       
  336.       
  337.     //Draw a square  
  338.     int i;  
  339.     glUseProgram(programHandle);  
  340.     for (i=2; i <= 4; i++)  
  341.     {  
  342.         /* Make our background black */  
  343.         glClearColor(0.0, 0.0, 0.0, 1.0);  
  344.         glClear(GL_COLOR_BUFFER_BIT);  
  345.    
  346.         /* Invoke glDrawArrays telling that our data is a line loop and we want to draw 2-4 vertexes */  
  347.         glDrawArrays(GL_TRIANGLE_FAN, 0, i);  
  348.    
  349.     }  
  350.    
  351.         // Unbind shader  
  352.     glUseProgram(0);  
  353.     SDL_GL_SwapBuffers( );  
  354.       
  355.     /* Gather our frames per second */  
  356.     Frames++;  
  357.     {  
  358.     GLint t = SDL_GetTicks();  
  359.     if (t - T0 >= 5000) {  
  360.         GLfloat seconds = (t - T0) / 1000.0;  
  361.         GLfloat fps = Frames / seconds;  
  362.         printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);  
  363.         T0 = t;  
  364.         Frames = 0;  
  365.     }  
  366.     }  
  367. }  
  368.   
  369. void initGL( int width, int height )  
  370. {  
  371.     float ratio = (float) width / (float) height;  
  372.     // Our shading model--Gouraud (smooth).  
  373.     glShadeModel( GL_SMOOTH );  
  374.     // Set the clear color.  
  375.     glClearColor( 0, 0, 0, 0 );  
  376.     // Setup our viewport.  
  377.     glViewport( 0, 0, width, height );  
  378.     //Change to the projection matrix and set our viewing volume.  
  379.     glMatrixMode( GL_PROJECTION );  
  380.     glLoadIdentity();  
  381.     gluPerspective( 60.0, ratio, 1.0, 100.0 );  
  382. }  
  383.   
  384. int main( int argc, char* argv[] )  
  385. {  
  386.   
  387.     // Color depth in bits of our window.  
  388.     int flags= SDL_OPENGL|SDL_RESIZABLE;  
  389.     //Set the SDL  
  390.     initSDL(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,flags);  
  391.     if(glewInit() != GLEW_OK) exit(EXIT_FAILURE);  
  392.     //Init vertext shader  
  393.     initShader();  
  394.     //Set the OpenGL  
  395.     initGL(SCREEN_WIDTH, SCREEN_HEIGHT );  
  396.   
  397.     //main loop  
  398.     while(true)  
  399.     {  
  400.         /* Process incoming events. */  
  401.         handleEvents( );  
  402.         /* Draw the screen. */  
  403.         renderGL( );  
  404.     }  
  405.     // Free Shader  
  406.     freeShader();  
  407.     return 0;  
  408. }  
/*****************************************************************************Copyright: 2013, ustc All rights reserved.contact:k283228391@126.comFile name: main.cDescription:Using VAO and VBO in opengl.Author:Silang QuanVersion: 1.0Date: 2013.8.1*****************************************************************************/#include <SDL/SDL.h>#include <GL/glew.h>#include <GL/gl.h>#include <GL/glu.h>#include <stdio.h>#include <stdlib.h>const int SCREEN_WIDTH = 800;const int SCREEN_HEIGHT =800;const int SCREEN_BPP = 32;SDL_Surface *screen;//Whether the window is windowed or notbool windowed;//Whether the window is finebool windowOK;//Handler for GLSL programGLuint programHandle;GLuint vShader;GLuint fShader;GLuint vao, vbo[2];void quit( int code ){    SDL_Quit( );    /* Exit program. */    exit( code );}char *textFileRead(char *fn) {     FILE *fp;    char *content = NULL;     int count=0;     if (fn != NULL) {        fp = fopen(fn,"rt");         if (fp != NULL) {       fseek(fp, 0, SEEK_END);      count = ftell(fp);      rewind(fp);             if (count > 0) {                content = (char *)malloc(sizeof(char) * (count+1));                count = fread(content,sizeof(char),count,fp);                content[count] = '\0';            }            fclose(fp);        }    }    return content;}void toggle_fullscreen(){//If the screen is windowedif( windowed == true ){//Set the screen to fullscreenscreen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE| SDL_FULLSCREEN );//If there's an errorif( screen == NULL ){windowOK = false;return;}//Set the window state flagwindowed = false;}//If the screen is fullscreenelse if( windowed == false ){//Window the screenscreen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE );//If there's an errorif( screen == NULL ){windowOK = false;return;}//Set the window state flagwindowed = true;}}void handleKeyEvent( SDL_keysym* keysym ){    switch( keysym->sym ){    case SDLK_ESCAPE:        quit( 0 );        break;    case SDLK_SPACE:        break;    case SDLK_F1:toggle_fullscreen();break;    default:        break;    }}void resizeGL(int width,int height){    if ( height == 0 )    {        height = 1;    }    //Reset View    glViewport( 0, 0, (GLint)width, (GLint)height );    //Choose the Matrix mode    glMatrixMode( GL_PROJECTION );    //reset projection    glLoadIdentity();    //set perspection    gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );    //choose Matrix mode    glMatrixMode( GL_MODELVIEW );    glLoadIdentity();}void handleEvents(){    // Our SDL event placeholder.    SDL_Event event;    //Grab all the events off the queue.    while( SDL_PollEvent( &event ) ) {        switch( event.type ) {        case SDL_KEYDOWN:            // Handle key Event            handleKeyEvent( &event.key.keysym );            break;        case SDL_QUIT:            // Handle quit requests (like Ctrl-c).            quit( 0 );            break;        case SDL_VIDEORESIZE://Handle resize event            screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 16,                                      SDL_OPENGL|SDL_RESIZABLE);            if ( screen )            {                resizeGL(screen->w, screen->h);            }            break;        }    }}void initSDL(int width,int height,int bpp,int flags){    // First, initialize SDL's video subsystem.    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )    {        fprintf( stderr, "Video initialization failed: %s\n",                 SDL_GetError( ) );        quit( 1 );    }    atexit(SDL_Quit);//Set some Attribute of OpenGL in SDL    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );    //Set the video mode    screen= SDL_SetVideoMode( width, height, bpp,flags);    if(!screen )    {        fprintf( stderr, "Video mode set failed: %s\n",SDL_GetError( ) );        quit( 1 );    windowed=false;}else windowed=true;    resizeGL(screen->w, screen->h);    //Set caption    SDL_WM_SetCaption( "OpenGL Shading Language Test", NULL );    }void initShader(){//Init VAO and VBO /* 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]);        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]);        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);vShader = glCreateShader( GL_VERTEX_SHADER );fShader = glCreateShader( GL_FRAGMENT_SHADER );printf("Here\n");if(0 == vShader || 0 == fShader){fprintf(stderr, "Error creating vertex shader.\n");quit(1);}GLchar* vShaderCode = textFileRead("basic.vert");GLchar* fShaderCode = textFileRead("basic.frag");const GLchar* vCodeArray[1] = {vShaderCode};const GLchar* fCodeArray[1] = {fShaderCode};glShaderSource(vShader, 1, vCodeArray, NULL);glShaderSource(fShader, 1, fCodeArray, NULL);glCompileShader(vShader);glCompileShader(fShader);free(vShaderCode);free(fShaderCode);//const GLchar* codeArray[] = {shaderCode};//Check the compile resultGLint logLen;glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &logLen);if(logLen > 0){char *log = (char *)malloc(logLen);GLsizei written;glGetShaderInfoLog(vShader, logLen, &written, log);printf("Shader compile error log: %s\n",log);free(log);}programHandle = glCreateProgram();if(0 == programHandle){fprintf(stderr, "Error creating programHandle.\n");quit(1);}glAttachShader(programHandle, vShader);glAttachShader(programHandle, fShader);glBindAttribLocation(programHandle, 0, "in_Position");glBindAttribLocation(programHandle, 1, "in_Color");glLinkProgram(programHandle);//glUseProgram(programHandle);}void freeShader(){glDisableVertexAttribArray(0);    glDisableVertexAttribArray(1);glDetachShader(programHandle, fShader);glDetachShader(programHandle, vShader);//glDeteteProgram(programHandle);glDeleteShader(fShader);glDeleteShader(vShader);glDeleteBuffers(2, vbo);    glDeleteVertexArrays(1, &vao);}void renderGL(){/* These are to calculate our fps */    static GLint T0     = 0;static GLint Frames = 0;    // Clear the color and depth buffers.    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );    // We don't want to modify the projection matrix. */    glMatrixMode( GL_MODELVIEW );    glLoadIdentity( );    // Move down the z-axis.    glTranslatef( 0.0, 0.0, -5.0 );               //Draw a squareint i;    glUseProgram(programHandle); 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_TRIANGLE_FAN, 0, i);     }         // Unbind shader    glUseProgram(0);   SDL_GL_SwapBuffers( );        /* Gather our frames per second */    Frames++;    {GLint t = SDL_GetTicks();if (t - T0 >= 5000) {    GLfloat seconds = (t - T0) / 1000.0;    GLfloat fps = Frames / seconds;    printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);    T0 = t;    Frames = 0;}    }}void initGL( int width, int height ){    float ratio = (float) width / (float) height;    // Our shading model--Gouraud (smooth).    glShadeModel( GL_SMOOTH );    // Set the clear color.    glClearColor( 0, 0, 0, 0 );    // Setup our viewport.    glViewport( 0, 0, width, height );    //Change to the projection matrix and set our viewing volume.    glMatrixMode( GL_PROJECTION );    glLoadIdentity();    gluPerspective( 60.0, ratio, 1.0, 100.0 );}int main( int argc, char* argv[] ){// Color depth in bits of our window.int flags= SDL_OPENGL|SDL_RESIZABLE;//Set the SDLinitSDL(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,flags);if(glewInit() != GLEW_OK) exit(EXIT_FAILURE);//Init vertext shaderinitShader();//Set the OpenGLinitGL(SCREEN_WIDTH, SCREEN_HEIGHT );    //main loop    while(true){        /* Process incoming events. */        handleEvents( );        /* Draw the screen. */        renderGL( );    }    // Free Shader    freeShader();    return 0;}

编译
g++ main.c -o main -lSDL -lglut -lGLU -lGLEW



程序解释:

主要看initShader函数。

       首先时定义了二维坐标数组dimond和三维的颜色数组colors,然后,通过 glGenVertexArrays生成VAO,通过glGenBuffers生成VBO。Vao中包含着顶点的信息和数据的连接信息。 glVertexAttribPointer用于定义数据的index,存在buffer中的数据格式,在shader中会用到。

       接下来时初始化shader,这个在上面说了。

       initShader    就是做shader render之前的准备工作。

       接下来的renderGL函数,用到glClear 清除color buffer,绘制使用的函数是glDrawArray。

原创粉丝点击