原文参考地址:http://www.cnblogs.com/zilongshanren/archive/2011/08/08/2131019.html

一、编译Vertex Shaders和Fragment Shaders

  目前为止,xcode仅仅会把这个两个文件(simple.vertsh和simple.fragsh)copy到application bundle中。我们还需要在运行编译和运行这些Shaders。

  你会很诧异,为什么要在app运行时编译代码?

  这样做的好处是:我们的Shaders不用依赖于某种图形芯片(这样可以跨平台嘛)。

  下面开始加入动态编译的代码(两种方式。1.直接在OpenGLView写入;2.创建工具类)

  我选用第二种方式创建动态编译的代码:

  在Project中,新建继承NSObject的LVApplicationShaderUtils类。

  贴下代码:

- (GLuint)compileShader:(NSString *)shaderFileName withType:(GLenum)shaderType
{
NSString * shaderName = [[shaderFileName lastPathComponent] stringByDeletingPathExtension];
NSString * shaderFileType = [shaderFileName pathExtension];
NSLog(@"文件名称:%@ 文件类型:%@",shaderName,shaderFileType); //!> 1
NSString * shaderPath = [[NSBundle mainBundle] pathForResource:shaderName ofType:shaderFileType];
NSLog(@"文件路径:%@",shaderPath); NSError * error = nil;
NSString * shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:&error];
if (!shaderPath)
{
NSLog(@"错误加载shader(%@):%@",shaderFileName,error.localizedDescription);
return ;
} //!> 2
GLuint shaderHandle = glCreateShader(shaderType); //!> 3
const char * shaderStringUTF8 = [shaderString UTF8String];
GLint shaderStringLength = (GLint)[shaderString length];
glShaderSource(shaderHandle, , &shaderStringUTF8, &shaderStringLength); //!> 4
glCompileShader(shaderHandle); //!> 5
GLint compileSuccess;
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
if (compileSuccess == GL_FALSE)
{
GLchar messages[];
glGetShaderInfoLog(shaderHandle, sizeof(messages), , &messages[]);
NSString * messageString = [NSString stringWithUTF8String:messages];
NSLog(@"错误编译shader(%@):%@",shaderFileName,messageString);
return ;
} return shaderHandle;
}

如果你感觉跟入门笔记一中的方法有很多不同,恭喜你。

1.找到.vertsh 和 .fragsh文件路径。

2.调用glCreateShader来创建一个代表shader的OpenGL对象,需要一个参数

/* Shaders */
#define GL_FRAGMENT_SHADER 0x8B30 // 代表片元着色器类型对象
#define GL_VERTEX_SHADER 0x8B31 // 代表顶点着色器类型对象

3.glShaderSource,让OpenGL获取到这个Shader的源代码,把NSString文件内容转换成C-String(null-terminated string)。

4.最后,调用glCompileShader在运行时编译Shader。

5.使用glGetShaderiv和glGetShaderInfoLog打印error日志。

/* Boolean */
#define GL_FALSE 0
#define GL_TRUE 1
GLint compileSuccess;
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
if (compileSuccess == GL_FALSE)
{
GLchar messages[];
glGetShaderInfoLog(shaderHandle, sizeof(messages), , &messages[]);
NSString * messageString = [NSString stringWithUTF8String:messages];
NSLog(@"错误编译shader(%@):%@",shaderFileName,messageString);
return ;
}

判断异常常规写法

这个代码写法一般都是这样写的。可以直接copy~~

二、如果编译好了Vertex Shader和Fragment Shader之后,我们需要把两个Shader关联起来。

typedef NS_ENUM(NSInteger,compileProgramError)
{
compileProgramErrorShaders = -, //!> Shader创建失败
compileProgramErrorProgram = -, //!> Program object 创建失败
compileProgramErrorLink = - //!> link 失败
};
- (NSInteger)linkProgramHandle
{
//!> 1
GLuint vertexShader = [self compileShader:@"Simple.vertsh" withType:GL_VERTEX_SHADER];
GLuint fragmentShader = [self compileShader:@"Simple.fragsh" withType:GL_FRAGMENT_SHADER];
if ((vertexShader == )||(fragmentShader == ))
{
NSLog(@"错误:错误编译Shaders");
return compileProgramErrorShaders;
} //!> 2
GLuint programHandle = glCreateProgram();
if (programHandle == )
{
NSLog(@"错误:不能创建Program object");
return compileProgramErrorProgram;
}
glAttachShader(programHandle, vertexShader);
glAttachShader(programHandle, fragmentShader);
glLinkProgram(programHandle); //!>3
GLint linkSuccess;
glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
if (linkSuccess == GL_FALSE)
{
GLchar messages[];
glGetProgramInfoLog(programHandle, sizeof(messages), , &messages[]);
NSString * messageString = [NSString stringWithUTF8String:messages];
NSLog(@"Error link Shaders:%@",messageString);
return compileProgramErrorLink;
}
return programHandle;
}

解析:

1.用compileShader方法动态编译了Vertex Shader和Fragment Shader两个对象。

2.调用glCreateProgram、glAttachShader、glLinkProgram连接Vertex Shader和Fragment Shader形成一个完成的Program。

3.调用glGetProgram、glGetProgramInfoLog方法来检查error,跟动态编译Shader的方法中检查方法类似。

GLint linkSuccess;
glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
if (linkSuccess == GL_FALSE)
{
GLchar messages[];
glGetProgramInfoLog(programHandle, sizeof(messages), , &messages[]);
NSString * messageString = [NSString stringWithUTF8String:messages];
NSLog(@"Error link Shaders:%@",messageString);
return compileProgramErrorLink;
}

检查是否有error

常规方法都是这样写的,也是可以直接copy的哦~~

最后准确无误了,就返回programHandle,项目句柄 

三、接下来让OpenGL执行Program,使用的就是programHandle。 

OpenGL示例代码:https://github.com/nLoser/OpenGLES_Study

OpenGLES入门笔记四的更多相关文章

  1. OpenGLES入门笔记三

    在入门笔记一中比较详细的介绍了顶点着色器和片面着色器. 在入门笔记二中讲解了简单的创建OpenGL场景流程的实现,但是如果在场景中渲染任何一种几何图形,还是需要入门笔记一中的知识:Vertex Sha ...

  2. OpenGLES入门笔记一

    学习地址:http://www.raywenderlich.com/3664/opengl-tutorial-for-ios-opengl-es-2-0 中文翻译:http://www.cnblogs ...

  3. OpenGLES入门笔记二

    #import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> #import <OpenGLES/ES2/gl.h& ...

  4. SpringBoot入门笔记(四)、通常Mybatis项目目录结构

    1.工程启动类(AppConfig.java) 2.实体类(domain) 3.数据访问层(dao) 4.数据服务层(service) 5.前端控制器(controller) 6.工具类(util) ...

  5. React.js入门笔记

    # React.js入门笔记 核心提示 这是本人学习react.js的第一篇入门笔记,估计也会是该系列涵盖内容最多的笔记,主要内容来自英文官方文档的快速上手部分和阮一峰博客教程.当然,还有我自己尝试的 ...

  6. redis入门笔记(2)

    redis入门笔记(2) 上篇文章介绍了redis的基本情况和支持的数据类型,本篇文章将介绍redis持久化.主从复制.简单的事务支持及发布订阅功能. 持久化 •redis是一个支持持久化的内存数据库 ...

  7. redis入门笔记(1)

    redis入门笔记(1) 1. Redis 简介 •Redis是一款开源的.高性能的键-值存储(key-value store).它常被称作是一款数据结构服务器(data structure serv ...

  8. MySQL入门笔记

    MySQL入门笔记 版本选择: 5.x.20 以上版本比较稳定 一.MySQL的三种安装方式: 安装MySQL的方式常见的有三种: ·          rpm包形式 ·          通用二进制 ...

  9. MySQL入门笔记(一)

    一.数据类型 1. 整型 2. 浮点型 3. 字符型 4. 日期时间型 二.数据库操作 1. 创建库 CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_nam ...

随机推荐

  1. 记一次ASP.NET网站的入侵和如何避免被入侵

    ASP.NET网站入侵第二波(LeaRun.信息化快速开发框架 已被笔者拿下) 详细介绍请看第二波 首先我要申明的是不是什么语言写出来的程序就不安全,而是得看写代码的人如何去写这个程序 前些日子我去客 ...

  2. C#读书雷达

    大家都知道,ThoughtWorks的技术雷达每年都会发布两到三次,它不但是业界技术趋势的标杆,更提供了一种卓有成效的方法论,即打造自己的技术雷达.在这种思想的驱动下,我们诞生了自己的读书雷达(目前已 ...

  3. 数据库系统原理——ER模型与关系模型

    原文链接: http://blog.csdn.net/haovip123/article/details/21614887 犹记得第一次看<数据库系统原理>时看天书的感觉,云里雾里:现在已 ...

  4. C# Image Resizer

    This program is used to resize images. using System; using System.Windows.Forms; using System.Drawin ...

  5. android listview 的监听事件

    今天遇到了一个比较让我头疼的问题,不过追根揭底只是我对listview理解的不够透彻罢了, 闲言少叙,说说我遇到的问题吧: 上篇随笔我写了关于listview的使用,如果你也已经写好了列表那么恭喜这一 ...

  6. 作业成绩 final-review 20161201-1203 15:05

    final-review阶段,20161201-20161203 15:05 final 评论II截止 20161204 09:00 申诉截止时间 20161207 12:00,微信联系杨贵福. 凡描 ...

  7. Beta--项目冲刺第七天

    胜利在望-- 队伍:F4 成员:031302301 毕容甲 031302302 蔡逸轩 031302430 肖阳 031302418 黄彦宁 会议内容: 1.站立式会议照片: 2.项目燃尽图 3.冲刺 ...

  8. Entity Framework Code First (六)存储过程

    声明:本文只针对 EF6+ 默认情况下,Code First 对实体进行插入.更新.删除操作是直接在表上进行的,从 EF6 开始你可以选择使用存储过程(Stored Procedures) 简单实体映 ...

  9. JavaScript使用自定义事件实现简单的模块化开发

    WEB前端最常见驱动方式就是事件了, 所有交互等等都是通过事件,前端的常见事件有: UI事件: 焦点事件: 鼠标事件: 滚轮事件: 文本事件: 键盘事件: 变动事件: 现在网页上有一个输入框, 如果我 ...

  10. js-处理回车事件

    /**回车 */ function enterkey() { //兼容IE或其它其它浏览器 var event = arguments[0] || window.event; //兼容IE或其它浏览器 ...