2.一个例子简单说明OpenGL ES流程,注释超详细

typedef struct
{
   GLuint programObject;
} UserData;

//创建着色器程序并返回着色器句柄
GLuint LoadShader ( GLenum type, const char *shaderSrc )
{
   GLuint shader;
   GLint compiled;
    //创建着色器,获得句柄,type = GL_VERTEX_SHADER | GL_FRAGMENT_SHADER
   shader = glCreateShader ( type );
	//是否创建成功
   if ( shader == 0 )
   {
      return 0;
   }

   // 将创建的着色器与着色器程序关联,最后一个参数为数组长度,如果为NULL,则自动计算数组长度
   glShaderSource ( shader, 1, &shaderSrc, NULL );

   //编译着色器字符串源代码,
   glCompileShader ( shader );

   //编译着色器可能失败,  编译状态将存储为着色器对象的状态的一部分。 如果着色器编译时没有错误并且可以使用,则此值将设置为GL_TRUE,否则将设置为GL_FALSE。 
   //可以通过使用参数shader和GL_COMPILE_STATUS调用glGetShaderiv来查询状态值。
   glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );

   if ( !compiled )
   {
       /*
       主要为异常情况信息的打印及处理
       */
      GLint infoLen = 0;
 	  //获得log的长度
      glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );

      if ( infoLen > 1 )
      {		//申请log长度内存
         char *infoLog = malloc ( sizeof ( char ) * infoLen );
			//得到log内容
         glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
          	//输出log内容-宏定义log,基于各平台实现
         LOGD( "Error compiling shader:\n%s\n", infoLog );
         free ( infoLog );
      }
	  //标记为删除,撤销glCreateShader的调用
      //如果要删除的着色器对象附加到程序对象,它将被标记为删除,但它不会被删除,直到它不再附加到任何程序对象,
      //对于任何渲染上下文(即,它必须与 它被附加之前的任何地方都将被删除)。shader为0将被忽视。
      //要确定对象是否已标记为删除,可以使用参数shader和GL_DELETE_STATUS调用glGetShaderiv。
      glDeleteShader ( shader );
      return 0;
   }
   return shader;

}

int Init ( ESContext *esContext )
{
   UserData *userData = esContext->userData;
    //声明顶点着色器字符串源码
   char vShaderStr[] =
      "#version 300 es                          \n"
      "layout(location = 0) in vec4 vPosition;  \n"
      "void main()                              \n"
      "{                                        \n"
      "   gl_Position = vPosition;              \n"
      "}                                        \n";
	//声明片段着色器字符串源码
   char fShaderStr[] =
      "#version 300 es                              \n"
      "precision mediump float;                     \n"
      "out vec4 fragColor;                          \n"
      "void main()                                  \n"
      "{                                            \n"
      "   fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );  \n"
      "}                                            \n";
	
   GLuint vertexShader;
   GLuint fragmentShader;
   GLuint programObject;
   GLint linked;

   //创建两种着色器
   vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
   fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );

   //创建着色器program,相当于着色器的容器?
   programObject = glCreateProgram ( );
	//异常情况判断,是否创建成功
   if ( programObject == 0 )
   {
      return 0;
   }
	//将着色器附加到program中
   glAttachShader ( programObject, vertexShader );
   glAttachShader ( programObject, fragmentShader );

   //连接着色器程序
   glLinkProgram ( programObject );

   //获取program连接状态,与glGetShaderiv方法类似
   glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );

   if ( !linked )
   {
       /*
       	异常情况处理,与创建着色器时类似
       */
       
      GLint infoLen = 0;

      glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );

      if ( infoLen > 1 )
      {
         char *infoLog = malloc ( sizeof ( char ) * infoLen );

         glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
         LOGE ( "Error linking program:\n%s\n", infoLog );

         free ( infoLog );
      }

      glDeleteProgram ( programObject );
      return FALSE;
   }

   userData->programObject = programObject;
	// 为颜色缓冲区指定清除值,取值范围都是0~1.0f,注意,此操作只是指定指,而非渲染,执行此方法,屏幕不会发生变化
    // 执行了glClear ( GL_COLOR_BUFFER_BIT ); 之后,glClearColor指定的颜色才会生效
    // 四个参数分别为R、G、B、A
   glClearColor ( 1.0f, 1.0f, 1.0f, 0.0f );
   return TRUE;
}

void Draw ( ESContext *esContext )
{
   UserData *userData = esContext->userData;
    //opengl 坐标原点默认给在屏幕中间,顶点坐标分别为xyz,可以画出图元形状
   GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f,
                            -0.5f, -0.5f, 0.0f,
                            0.5f, -0.5f, 0.0f
                         };

   //设置视口,可渲染的区域,指定视口矩形的左下角坐标
   glViewport ( 0, 0, esContext->width, esContext->height );

    //GL_COLOR_BUFFER_BIT:表示当前启用了颜色写入的缓冲区。
	//GL_DEPTH_BUFFER_BIT:深度缓冲区。
	//GL_STENCIL_BUFFER_BIT:指示模板缓冲区。
    //清除每个缓冲区的值取决于该缓冲区的清除值的设置。
    //设置的视口如果为屏幕大小,则其实清除值就是窗口的背景颜色,如果为静态背景,可以只执行一次。
    //执行效率比手动涂抹背景画布效率更高,节省资源。
    //像素检验、裁剪检验、抖动和缓存的写屏蔽都会影响glClear的操作,其中,裁剪范围限制了清除的区域,而glClear命令还会忽略alpha函数、融合函数、逻辑操作、模板、纹理映射和z缓存;
   glClear ( GL_COLOR_BUFFER_BIT );
	
    //使用创建的着色器program
   glUseProgram ( userData->programObject );

   //指定通用顶点属性数组
   /*
   *@param index		:指定要修改的通用顶点属性的索引。
   *@param size			:指定每个通用顶点属性的组件数。 必须为1,2,3或4.初始值为4。
   *@param type			:指定数组中每个组件的数据类型。 接受符号常量GL_BYTE,GL_UNSIGNED_BYTE,GL_SHORT,GL_UNSIGNED_SHORT,GL_FIXED或GL_FLOAT。 初始值为GL_FLOAT。
   *@param normalized	:指定在访问定点数据值时是应将其标准化(GL_TRUE)还是直接转换为定点值(GL_FALSE)。
   *@param stride		:指定连续通用顶点属性之间的字节偏移量。 如果stride为0,则通用顶点属性被理解为紧密打包在数组中的。 初始值为0。
   *@param pointer		:指定指向数组中第一个通用顶点属性的第一个组件的指针。 初始值为0。
   */
   glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
    //启用顶点属性数组
   glEnableVertexAttribArray ( 0 );
	//从数组数组中渲染图元:图元种类,三角形、线、点精灵
   glDrawArrays ( GL_TRIANGLES, 0, 3 );
}

void Shutdown ( ESContext *esContext )
{
   UserData *userData = esContext->userData;
	//删除释放着色器program
   glDeleteProgram ( userData->programObject );
}

int esMain ( ESContext *esContext )
{
   esContext->userData = malloc ( sizeof ( UserData ) );

   esCreateWindow ( esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB );

   if ( !Init ( esContext ) )
   {
      return GL_FALSE;
   }

   esRegisterShutdownFunc ( esContext, Shutdown );
   esRegisterDrawFunc ( esContext, Draw );

   return GL_TRUE;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值