OpenGLES入门笔记四
原文参考地址: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入门笔记四的更多相关文章
- OpenGLES入门笔记三
在入门笔记一中比较详细的介绍了顶点着色器和片面着色器. 在入门笔记二中讲解了简单的创建OpenGL场景流程的实现,但是如果在场景中渲染任何一种几何图形,还是需要入门笔记一中的知识:Vertex Sha ...
- OpenGLES入门笔记一
学习地址:http://www.raywenderlich.com/3664/opengl-tutorial-for-ios-opengl-es-2-0 中文翻译:http://www.cnblogs ...
- OpenGLES入门笔记二
#import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> #import <OpenGLES/ES2/gl.h& ...
- SpringBoot入门笔记(四)、通常Mybatis项目目录结构
1.工程启动类(AppConfig.java) 2.实体类(domain) 3.数据访问层(dao) 4.数据服务层(service) 5.前端控制器(controller) 6.工具类(util) ...
- React.js入门笔记
# React.js入门笔记 核心提示 这是本人学习react.js的第一篇入门笔记,估计也会是该系列涵盖内容最多的笔记,主要内容来自英文官方文档的快速上手部分和阮一峰博客教程.当然,还有我自己尝试的 ...
- redis入门笔记(2)
redis入门笔记(2) 上篇文章介绍了redis的基本情况和支持的数据类型,本篇文章将介绍redis持久化.主从复制.简单的事务支持及发布订阅功能. 持久化 •redis是一个支持持久化的内存数据库 ...
- redis入门笔记(1)
redis入门笔记(1) 1. Redis 简介 •Redis是一款开源的.高性能的键-值存储(key-value store).它常被称作是一款数据结构服务器(data structure serv ...
- MySQL入门笔记
MySQL入门笔记 版本选择: 5.x.20 以上版本比较稳定 一.MySQL的三种安装方式: 安装MySQL的方式常见的有三种: · rpm包形式 · 通用二进制 ...
- MySQL入门笔记(一)
一.数据类型 1. 整型 2. 浮点型 3. 字符型 4. 日期时间型 二.数据库操作 1. 创建库 CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_nam ...
随机推荐
- 开发WP版本的大菠萝英雄榜
前言 想当年Team有无数人在玩大菠萝,我被忽悠进来做肉盾,选了蛮子,从1.0开始,经历了103.105.108.2.0.2.1.这个游戏对我最大的帮助是学习了不同的技术,比如XAML.比如xcode ...
- 曼慧尼特u检验(两个样本数据间有无差异)
曼-惠特尼U检验(Mann-Whitney检验) How the Mann-Whitney test works Mann-Whitney检验又叫做秩和检验,是比较没有配对的两个独立样本的非参数检验. ...
- HttpWebRequest提交(Post)数据
protected void Page_Load(object sender, EventArgs e) { string sql = "select top 1 * from [user] ...
- 关于QString中的arg()函数使用方法
例:正确做法:ui->label->setText(QString("Processingfile%1").arg(index));错误做法: ui->label ...
- 从库查看状态的时候显示“ Last_Error”
mysql> show slave status\G;*************************** 1. row *************************** ...
- 【转】css布局居中和CSS内容居中区别和对应DIV CSS代码
原文地址:http://www.divcss5.com/jiqiao/j771.shtml css布局居中和CSS内容居中区别和对应DIV CSS代码教程与图文代码案例篇 对于新手来说DIV CSS布 ...
- nginx正向代理,反向代理,透明代理(总结)
1正向代理 正向代理,也就是传说中的代理,他的工作原理就像一个跳板, 简单的说, 我是一个用户,我访问不了某网站,但是我能访问一个代理服务器 这个代理服务器呢,他能访问那个我不能访问的网站 于是我先连 ...
- Struts2+Spring+Mybatis+Junit 测试
Struts2+Spring+Mybatis+Junit 测试 博客分类: HtmlUnit Junit Spring 测试 Mybatis package com.action.kioskmoni ...
- [转]git在eclipse中的配置
一_安装EGIT插件 http://download.eclipse.org/egit/updates/ 或者使用Eclipse Marketplace,搜索EGit 二_使用EGIT前的配置 配置个 ...
- js-FCC算法-Symmetric Difference
创建一个函数,接受两个或多个数组,返回所给数组的 对等差分(symmetric difference) (△ or ⊕)数组. 给出两个集合 (如集合 A = {1, 2, 3} 和集合 B = {2 ...