OpenGL进阶(八) - GLSL入门

本文介绍了OpenGL着色语言(GLSL)在SDL环境下的应用,包括基本概念、编程环境设置、编写简单Shader的方法及OpenGL环境配置,旨在通过GPU加速显著提升渲染速度并解放CPU。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

        随着图形硬件的发展,渲染管线由固定不可更改想着可编程和更平滑的方向不断发展。越来越多的基于GPU的编程语言开始出现,cg,cuda,各种着色语言等等。

        今天要介绍的就是和OpenGL结合非常紧密的GLSL(OpenGL Shading Language). 通过OpenGL的API我们可以绘制图元,变换图形等等,当并不能改变基础的渲染管线。在OpenGL中使用GLSL,就能将渲染管线中固定的功能阶段转变成可编程的。

        编程环境:Ubuntu12.04 32bit  GTX480

GLSL简介

         OpenGL着色语言(GLSL――OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分。比如:视图转换、投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器),有时还会有Geometry Shader(几何着色器)。负责运行顶点着色的是顶点着色器。它可以得到当前OpenGL 中的状态,GLSL内置变量进行传递。它拥有一下的一些特点:

1.是一种高级的过程式语言;

2.作为OpenGL标准的一个部分,也就意味着开源,跨平台;

3.基于C和C++的语法和流程控制;

4.天然支持向量和矩阵的运算;

5.比C和C++更加严格的变量控制;

6.使用变量来处理输入和输出而不是读写文档;

7.Shader的长度并没有限制,也没有必要去查询。

     为什要使用OpenGL shader?

1.增加材料的真材实感 - 石头,草地,木头等等;

2.增加光照效果的真材实感 - 面光源,软阴影等等;

3.高级的渲染效果 - 全局照明,光线追踪等等;

4.非真实的材质 - 模拟画笔效果,钢笔绘制效果等等;

5.阶段贴图 - 动态生成2D和3D的纹理,而不是静态的图像;

6.图像处理 - 卷积,遮罩,复杂混合等;

7.动态效果 - 关键帧插值,粒子系统,动画;

8.可编程反走样方法;

9.通用计算 - 排序,数学建模,流体计算;

这些特性在使用opengl的时候可能可以去实现,但是都会有些局限,而现在,通过shader,我们可以通过显卡的硬件加速来显著增加渲染的速度,同时可以解放CPU。


写一个简单的Shader

首先来看一下电脑的OpenGL环境,终端运行:

glxinfo | grep OpenGL



基于SDL的OpenGL已经安装好(参考这里:SDL入门学习),接下来需要安装一下OpenGL的扩展库。

sudo apt-get install glew-utils libglew1.6


这次先绘制一个简单的矩形。

在工程文件夹下创建一个basic.vert,作为vertex shader.

  1. #version 400  
  2. in vec3 VertexPosition;  
  3. in vec3 VertexColor;  
  4. out vec3 Color;  
  5. void main()  
  6. {  
  7.     Color = VertexColor;  
  8.     gl_Position = vec4( VertexPosition, 1.0);  
  9. }  
#version 400
in vec3 VertexPosition;
in vec3 VertexColor;
out vec3 Color;
void main()
{
	Color = VertexColor;
	gl_Position = vec4( VertexPosition, 1.0);
}

·in – for input parameters
·out – for outputs of the function. The returnstatement is also an option for sending the result of a function.
·inout – for parameters that are both input andoutput of a function (新版本的GLSL似乎已经废除)

再创建一个basic.frag,作为fragment shader.

  1. #version 400   
  2. void main(void)  
  3. {  
  4.     gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);  
  5. }  
#version 400
void main(void)
{
	gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}

创建main.c,代码如下:

  1. /***************************************************************************** 
  2. Copyright: 2013, ustc All rights reserved. 
  3. contact:k283228391@126.com 
  4. File name: main.c 
  5. Description:Using opengl shading language in SDL. 
  6. Author:Silang Quan 
  7. Version: 1.0 
  8. Date: 2013.7.30 
  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.   
  31. void quit( int code )  
  32. {  
  33.     SDL_Quit( );  
  34.     /* Exit program. */  
  35.     exit( code );  
  36. }  
  37.   
  38. char *textFileRead(char *fn) {  
  39.    
  40.     FILE *fp;  
  41.     char *content = NULL;  
  42.    
  43.     int count=0;  
  44.    
  45.     if (fn != NULL) {  
  46.         fp = fopen(fn,"rt");  
  47.    
  48.         if (fp != NULL) {  
  49.    
  50.       fseek(fp, 0, SEEK_END);  
  51.       count = ftell(fp);  
  52.       rewind(fp);  
  53.    
  54.             if (count > 0) {  
  55.                 content = (char *)malloc(sizeof(char) * (count+1));  
  56.                 count = fread(content,sizeof(char),count,fp);  
  57.                 content[count] = '\0';  
  58.             }  
  59.             fclose(fp);  
  60.         }  
  61.     }  
  62.     return content;  
  63. }  
  64.   
  65. void toggle_fullscreen()  
  66. {  
  67.     //If the screen is windowed   
  68.     if( windowed == true )  
  69.     {  
  70.         //Set the screen to fullscreen   
  71.         screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE| SDL_FULLSCREEN );  
  72.   
  73.         //If there's an error   
  74.         if( screen == NULL )  
  75.         {  
  76.             windowOK = false;  
  77.             return;  
  78.         }  
  79.   
  80.         //Set the window state flag   
  81.         windowed = false;  
  82.     }  
  83.     //If the screen is fullscreen   
  84.     else if( windowed == false )  
  85.     {  
  86.         //Window the screen   
  87.         screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE );  
  88.   
  89.         //If there's an error   
  90.         if( screen == NULL )  
  91.         {  
  92.             windowOK = false;  
  93.             return;  
  94.         }  
  95.   
  96.         //Set the window state flag   
  97.         windowed = true;  
  98.     }  
  99. }  
  100.   
  101. void handleKeyEvent( SDL_keysym* keysym )  
  102. {  
  103.     switch( keysym->sym )  
  104.     {  
  105.     case SDLK_ESCAPE:  
  106.         quit( 0 );  
  107.         break;  
  108.     case SDLK_SPACE:  
  109.         break;  
  110.     case SDLK_F1:  
  111.         toggle_fullscreen();  
  112.         break;  
  113.     default:  
  114.         break;  
  115.     }  
  116. }  
  117.   
  118. void resizeGL(int width,int height)  
  119. {  
  120.     if ( height == 0 )  
  121.     {  
  122.         height = 1;  
  123.     }  
  124.     //Reset View   
  125.     glViewport( 0, 0, (GLint)width, (GLint)height );  
  126.     //Choose the Matrix mode   
  127.     glMatrixMode( GL_PROJECTION );  
  128.     //reset projection   
  129.     glLoadIdentity();  
  130.     //set perspection   
  131.     gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );  
  132.     //choose Matrix mode   
  133.     glMatrixMode( GL_MODELVIEW );  
  134.     glLoadIdentity();  
  135. }  
  136.   
  137. void handleEvents()  
  138. {  
  139.     // Our SDL event placeholder.   
  140.     SDL_Event event;  
  141.     //Grab all the events off the queue.   
  142.     while( SDL_PollEvent( &event ) ) {  
  143.         switch( event.type ) {  
  144.         case SDL_KEYDOWN:  
  145.             // Handle key Event   
  146.             handleKeyEvent( &event.key.keysym );  
  147.             break;  
  148.         case SDL_QUIT:  
  149.             // Handle quit requests (like Ctrl-c).   
  150.             quit( 0 );  
  151.             break;  
  152.         case SDL_VIDEORESIZE:  
  153.             //Handle resize event   
  154.             screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 16,  
  155.                                       SDL_OPENGL|SDL_RESIZABLE);  
  156.             if ( screen )  
  157.             {  
  158.                 resizeGL(screen->w, screen->h);  
  159.             }  
  160.             break;  
  161.         }  
  162.     }  
  163. }  
  164.   
  165. void initSDL(int width,int height,int bpp,int flags)  
  166. {  
  167.     // First, initialize SDL's video subsystem.   
  168.     if( SDL_Init( SDL_INIT_VIDEO ) < 0 )  
  169.     {  
  170.         fprintf( stderr, "Video initialization failed: %s\n",  
  171.                  SDL_GetError( ) );  
  172.         quit( 1 );  
  173.     }  
  174.     atexit(SDL_Quit);  
  175.     //Set some Attribute of OpenGL in SDL   
  176.     SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );  
  177.     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );  
  178.     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );  
  179.     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );  
  180.     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );  
  181.   
  182.     //Set the video mode   
  183.     screen= SDL_SetVideoMode( width, height, bpp,flags);  
  184.     if(!screen )  
  185.     {  
  186.         fprintf( stderr, "Video mode set failed: %s\n",SDL_GetError( ) );  
  187.         quit( 1 );  
  188.     windowed=false;  
  189.     }  
  190.     else windowed=true;  
  191.     resizeGL(screen->w, screen->h);  
  192.     //Set caption   
  193.     SDL_WM_SetCaption( "OpenGL Shading Language Test", NULL );  
  194.       
  195.   
  196. }  
  197.   
  198. void initShader()  
  199. {  
  200.       
  201.     vShader = glCreateShader( GL_VERTEX_SHADER );  
  202.     fShader = glCreateShader( GL_FRAGMENT_SHADER );  
  203.     printf("Here\n");  
  204.     if(0 == vShader || 0 == fShader)  
  205.     {  
  206.         fprintf(stderr, "Error creating vertex shader.\n");  
  207.         quit(1);  
  208.     }  
  209.       
  210.     GLchar* vShaderCode = textFileRead("basic.vert");  
  211.     GLchar* fShaderCode = textFileRead("basic.frag");  
  212.     const GLchar* vCodeArray[1] = {vShaderCode};  
  213.     const GLchar* fCodeArray[1] = {fShaderCode};  
  214.     glShaderSource(vShader, 1, vCodeArray, NULL);  
  215.     glShaderSource(fShader, 1, fCodeArray, NULL);  
  216.       
  217.     glCompileShader(vShader);  
  218.     glCompileShader(fShader);  
  219.     free(vShaderCode);  
  220.     free(fShaderCode);  
  221.     //const GLchar* codeArray[] = {shaderCode};   
  222.     //Check the compile result   
  223.     GLint logLen;  
  224.     glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &logLen);  
  225.     if(logLen > 0)  
  226.     {  
  227.         char *log = (char *)malloc(logLen);  
  228.         GLsizei written;  
  229.         glGetShaderInfoLog(vShader, logLen, &written, log);  
  230.         printf("Shader compile error log: %s\n",log);  
  231.         free(log);  
  232.     }  
  233.       
  234.     programHandle = glCreateProgram();  
  235.     if(0 == programHandle)  
  236.     {  
  237.         fprintf(stderr, "Error creating programHandle.\n");  
  238.         quit(1);  
  239.     }  
  240.       
  241.     glAttachShader(programHandle, vShader);  
  242.     glAttachShader(programHandle, fShader);  
  243.     glLinkProgram(programHandle);  
  244.     //glUseProgram(programHandle);   
  245. }  
  246.   
  247. void freeShader()  
  248. {  
  249.     glDetachShader(programHandle, fShader);  
  250.     glDetachShader(programHandle, vShader);  
  251.     glDeleteShader(fShader);  
  252.     glDeleteShader(vShader);  
  253.     //glDetachShader(fShader);   
  254.     //glDetachShader(vShader);   
  255.     //glDetachShader(programHandle);   
  256. }  
  257. void renderGL()  
  258. {  
  259.     /* These are to calculate our fps */  
  260.     static GLint T0     = 0;  
  261.     static GLint Frames = 0;  
  262.     // Clear the color and depth buffers.   
  263.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );  
  264.     // We don't want to modify the projection matrix. */   
  265.     glMatrixMode( GL_MODELVIEW );  
  266.     glLoadIdentity( );  
  267.     // Move down the z-axis.   
  268.     glTranslatef( 0.0, 0.0, -5.0 );  
  269.     //Draw a square   
  270.     glUseProgram(programHandle);  
  271.     glBegin(GL_QUADS);  
  272.             glVertex2f(-0.5f, -0.5f);  
  273.             glVertex2f( 0.5f, -0.5f);  
  274.             glVertex2f( 0.5f,  0.5f);  
  275.             glVertex2f(-0.5f,  0.5f);  
  276.     glEnd();  
  277.         // Unbind shader   
  278.     glUseProgram(0);  
  279.     SDL_GL_SwapBuffers( );  
  280.       
  281.     /* Gather our frames per second */  
  282.     Frames++;  
  283.     {  
  284.     GLint t = SDL_GetTicks();  
  285.     if (t - T0 >= 5000) {  
  286.         GLfloat seconds = (t - T0) / 1000.0;  
  287.         GLfloat fps = Frames / seconds;  
  288.         printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);  
  289.         T0 = t;  
  290.         Frames = 0;  
  291.     }  
  292.     }  
  293. }  
  294.   
  295. void initGL( int width, int height )  
  296. {  
  297.     float ratio = (float) width / (float) height;  
  298.     // Our shading model--Gouraud (smooth).   
  299.     glShadeModel( GL_SMOOTH );  
  300.     // Set the clear color.   
  301.     glClearColor( 0, 0, 0, 0 );  
  302.     // Setup our viewport.   
  303.     glViewport( 0, 0, width, height );  
  304.     //Change to the projection matrix and set our viewing volume.   
  305.     glMatrixMode( GL_PROJECTION );  
  306.     glLoadIdentity();  
  307.     gluPerspective( 60.0, ratio, 1.0, 100.0 );  
  308. }  
  309.   
  310. int main( int argc, char* argv[] )  
  311. {  
  312.   
  313.     // Color depth in bits of our window.   
  314.     int flags= SDL_OPENGL|SDL_RESIZABLE;  
  315.     //Set the SDL   
  316.     initSDL(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,flags);  
  317.     if(glewInit() != GLEW_OK) exit(EXIT_FAILURE);  
  318.     //Init vertext shader   
  319.     initShader();  
  320.     //Set the OpenGL   
  321.     initGL(SCREEN_WIDTH, SCREEN_HEIGHT );  
  322.   
  323.     //main loop   
  324.     while(true)  
  325.     {  
  326.         /* Process incoming events. */  
  327.         handleEvents( );  
  328.         /* Draw the screen. */  
  329.         renderGL( );  
  330.     }  
  331.     // Free Shader   
  332.     freeShader();  
  333.     return 0;  
  334. }  
/*****************************************************************************
Copyright: 2013, ustc All rights reserved.
contact:k283228391@126.com
File name: main.c
Description:Using opengl shading language in SDL.
Author:Silang Quan
Version: 1.0
Date: 2013.7.30
*****************************************************************************/
#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 not
bool windowed;
//Whether the window is fine
bool windowOK;
//Handler for GLSL program
GLuint programHandle;
GLuint vShader;
GLuint fShader;

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 windowed
	if( windowed == true )
	{
		//Set the screen to fullscreen
		screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE| SDL_FULLSCREEN );

		//If there's an error
		if( screen == NULL )
		{
			windowOK = false;
			return;
		}

		//Set the window state flag
		windowed = false;
	}
	//If the screen is fullscreen
	else if( windowed == false )
	{
		//Window the screen
		screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE );

		//If there's an error
		if( screen == NULL )
		{
			windowOK = false;
			return;
		}

		//Set the window state flag
		windowed = 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()
{
	
	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 result
	GLint 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);
	glLinkProgram(programHandle);
	//glUseProgram(programHandle);
}

void freeShader()
{
	glDetachShader(programHandle, fShader);
	glDetachShader(programHandle, vShader);
	glDeleteShader(fShader);
	glDeleteShader(vShader);
	//glDetachShader(fShader);
	//glDetachShader(vShader);
	//glDetachShader(programHandle);
}
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 square
    glUseProgram(programHandle);
    glBegin(GL_QUADS);
            glVertex2f(-0.5f, -0.5f);
            glVertex2f( 0.5f, -0.5f);
            glVertex2f( 0.5f,  0.5f);
            glVertex2f(-0.5f,  0.5f);
    glEnd();
        // 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 SDL
	initSDL(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,flags);
	if(glewInit() != GLEW_OK) exit(EXIT_FAILURE);
	//Init vertext shader
	initShader();
	//Set the OpenGL
	initGL(SCREEN_WIDTH, SCREEN_HEIGHT );

    //main loop
    while(true)
	{
        /* Process incoming events. */
        handleEvents( );
        /* Draw the screen. */
        renderGL( );
    }
    // Free Shader
    freeShader();
    return 0;
}

主要是增加了几个关于Shader的函数,initShader用于shader的初始化,freeShader用于删除shader,释放内存。使用shader之前还需要调用glewInit来初始化glew。


终端编译命令:

g++ main.c -o main -lSDL -lGL -lGLU -lGLEW



解释一下几个相关的API。

  1. GLuint glCreateShader(GLenum shaderType);  
  2. Parameter:  
  3.   
  4. shaderType – GL_VERTEX_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER, GL_TESS_EVALUATION_SHADER, or GL_FRAGMENT_SHADER.  
  5. Return Value:  
  6.   
  7. the shader handler  
GLuint glCreateShader(GLenum shaderType);
Parameter:

shaderType – GL_VERTEX_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER, GL_TESS_EVALUATION_SHADER, or GL_FRAGMENT_SHADER.
Return Value:

the shader handler

  1. void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lengthOfStrings);  
  2. Parameters:  
  3.   
  4. shader – the handler to the shader.  
  5. numOfStrings – the number of strings in the array.  
  6. strings – the array of strings.  
  7. lengthOfStrings – an array with the length of each string, or NULL, meaning that the strings are NULL terminated.  
void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lengthOfStrings);
Parameters:

shader – the handler to the shader.
numOfStrings – the number of strings in the array.
strings – the array of strings.
lengthOfStrings – an array with the length of each string, or NULL, meaning that the strings are NULL terminated.

  1. void glCompileShader(GLuint shader);  
  2. Parameters:  
  3.   
  4. shader – the handler to the shader.  
void glCompileShader(GLuint shader);
Parameters:

shader – the handler to the shader.


  1. void glUseProgram(GLuint program);  
  2.  Installs a program object as part of current rendering state  
  3. Parameters:  
  4. program  
  5. Specifies the handle of the program object whose executables are to be used as part of current rendering state.  
void glUseProgram(GLuint program);
 Installs a program object as part of current rendering state
Parameters:
program
Specifies the handle of the program object whose executables are to be used as part of current rendering state.


...

整个opengl程序执行的流程如下:


更多函数参考OpenGL reference - http://www.opengl.org/sdk/docs/man/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值