思维导图
画板.png
粘出核心代码
播放系统声音封装
+ (id)soundEffectWithContentsOfFile:(NSString *)aPath
{
return [[SoundEffect alloc] initWithContentsOfFile:aPath];
}
- (id)initWithContentsOfFile:(NSString *)path
{
if (!path)
{
return nil;
}
self = [super init];
if (self)
{
//1、获取声音文件路径
NSURL *aFileURL = [NSURL URLWithString:path];
if (aFileURL == nil)
{
return nil;
}
//2.获取声音文件id
SystemSoundID aSoundID;
OSStatus error = AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(aFileURL), &aSoundID);
if (error == kAudioServicesNoError)
{
//3.赋值
_soundID = aSoundID;
}
else
{
NSLog(@"Error :loading sound path,%d,%@",(int)error,path);
return nil;
}
}
return self;
}
//播放系统声音
- (void)play
{
AudioServicesPlaySystemSound(_soundID);
}
//释放
- (void)dealloc
{
AudioServicesDisposeSystemSoundID(_soundID);
}
Shader
{
for (int i = 0; i < NUM_PROGRAMS; i++) {
//读取顶点着色程序
char *vsrc = readFile(pathForResource(program[i].vert));
char *fsrc = readFile(pathForResource(program[i].frag));
//将char->NSString 对象
NSString *vsrcStr = [[NSString alloc]initWithBytes:vsrc length:strlen(vsrc)-1 encoding:NSUTF8StringEncoding];
NSString *fsrcStr = [[NSString alloc]initWithBytes:fsrc length:strlen(fsrc)-1 encoding:NSUTF8StringEncoding];
//打印着色程序中的代码
NSLog(@"vsrc:%@",vsrcStr);
NSLog(@"fsrc:%@",fsrcStr);
//attribute
GLsizei attribCt = 0;
//创建字符串数组【1】
GLchar *attribUsed[NUM_ATTRIBS];
//
GLint attrib[NUM_ATTRIBS];
//attribute 变量名称-inVertex(point.vsh)
GLchar *attribName[NUM_ATTRIBS] = {
"inVertex",
};
//uniform变量名称 "MVP", "pointSize", "vertexColor", "texture",
const GLchar *uniformName[NUM_UNIFORM] = {
"MVP", "pointSize", "vertexColor", "texture",
};
//遍历attribute
for (int j = 0; j < NUM_ATTRIBS; j++)
{
//strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。
//判断,attribute 变量,是否存在顶点着色器程序中。point.vsh
if (strstr(vsrc, attribName[j]))
{
//attribute个数
attrib[attribCt] = j;
//使用的attribute的名称
attribUsed[attribCt++] = attribName[j];
}
}
//利用shaderUtil.c封装好的方法对programe 进行创建、链接、生成Programe
/*
参数1:vsrc,顶点着色器程序
参数2:fsrc,片元着色器程序
参数3:attribute变量个数
参数4:attribute变量名称
参数5:当前attribute位置
参数6:uniform名字
参数7:program的uniform地址
参数8:program程序地址
*/
glueCreateProgram(vsrc,
fsrc,
attribCt,
(const GLchar **)&attribUsed[0],
attrib,
NUM_UNIFORM,
&uniformName[0],
program[i].uniform,
&program[i].program_id);
//释放vsrc,fsrc指针
free(vsrc);
free(fsrc);
// 设置常数、初始化Uniform
//当前的i == 0
if (i == PROGRAM_POINT)
{
//使用proram program[0].id 等价,以往课程例子中的GLuint program;
glUseProgram(program[PROGRAM_POINT].program_id);
//为当前程序对象指定uniform变量值
/*
为当前程序对象指定uniform变量MVP赋值
void glUniform1f(GLint location, GLfloat v0);
参数1:location,指明要更改的uniform变量的位置 MVP
参数2:v0,指明在指定的uniform变量中要使用的新值
program[0].uniform[3] = 0
等价于,vsh顶点着色器程序中的uniform变量,MVP = 0;
其实简单理解就是做了一次初始化,清空这个mat4矩阵
*/
glUniform1i(program[PROGRAM_POINT].uniform[UNIFORM_TEXTURE], 0);
// 投影矩阵
/*
投影分为正射投影和透视投影,我们可以通过它来设置投影矩阵来设置视域,在OpenGL中,默认的投影矩阵是一个立方体,即x y z 分别是-1.0~1.0的距离,如果超出该区域,将不会被显示
正射投影(orthographic projection):GLKMatrix4MakeOrtho(float left, float righ, float bottom, float top, float nearZ, float farZ),该函数返回一个正射投影的矩阵,它定义了一个由 left、right、bottom、top、near、far 所界定的一个矩形视域。此时,视点与每个位置之间的距离对于投影将毫无影响。
透视投影(perspective projection):GLKMatrix4MakeFrustum(float left, float right,float bottom, float top, float nearZ, float farZ),该函数返回一个透视投影的矩阵,它定义了一个由 left、right、bottom、top、near、far 所界定的一个平截头体(椎体切去顶端之后的形状)视域。此时,视点与每个位置之间的距离越远,对象越小。
在平面上绘制,只需要使正投影就可以了!!
*/
GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(0, backingWidth, 0, backingHeight, -1, 1);
//模型矩阵,比如你要平移、旋转、缩放,就可以设置在模型矩阵上
//这里不需要这些变换,则使用单元矩阵即可,相当于1 * ? = ?
GLKMatrix4 modelViewMatrix = GLKMatrix4Identity;
//矩阵相乘,就2个矩阵的结果交给MVPMatrix
GLKMatrix4 MVPMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
/*
void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
功能:为当前程序对象指定uniform变量值
参数1:location 指明要更改的uniform变量的位置 MVP
参数2:count 指定将要被修改的矩阵的数量
参数3:transpose 矩阵的值被载入变量时,是否要对矩阵进行变换,比如转置!
参数4:value ,指向将要用于更新uniform变量MVP的数组指针
*/
glUniformMatrix4fv(program[PROGRAM_POINT].uniform[UNIFORM_MVP], 1, GL_FALSE, MVPMatrix.m);
//点的大小 pointSize
/*
为当前程序对象指定uniform变量pointSize赋值
program[0].uniform[pointSize] = 纹理宽度/画笔比例
*/
glUniform1f(program[PROGRAM_POINT].uniform[UNIFORM_POINT_SIZE], brushTexture.width / kBrushScale);
//笔刷颜色
/*
为当前程序对象指定uniform变量vertexColor赋值
program[0].uniform[vertexColor] = 画笔颜色
void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
功能:为当前程序对象指定uniform变量值
参数1:location 指明要更改的uniform变量的位置 vertexColor
参数2:count 指定将要被修改的4分量的数量
参数3:value ,指向将要用于更新uniform变量vertexColor的值
*/
glUniform4fv(program[PROGRAM_POINT].uniform[UNIFORM_VERTEX_COLOR], 1, brushColor);
}
}
glError();
}
创建纹理图片
{
CGImageRef brushImage;
CGContextRef brushContext;
GLubyte *brushData;
size_t width,height;
GLuint texId;
textureInfo_t texture;
brushImage = [UIImage imageNamed:name].CGImage;
width = CGImageGetWidth(brushImage);
height = CGImageGetHeight(brushImage);
//初始化存贮图片所需要的空间
brushData = (GLubyte *)calloc(width * height * 4, sizeof(GLubyte));
//获取位图上下文
brushContext = CGBitmapContextCreate(brushData, width, height, 8, width * 4, CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast);
//绘制图片
CGContextDrawImage(brushContext, CGRectMake(0, 0, (CGFloat)width, (CGFloat)height), brushImage);
//接下来不需要上下文,所以可以进行释放
CGContextRelease(brushContext);
//OpenGL ES 生成纹理
//生成纹理标识
glGenTextures(1, &texId);
//绑定纹理标识
glBindTexture(GL_TEXTURE_2D, texId);
//设置纹理过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//指定2D纹理图像,为内存中的图像数据提供一个指针
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData);
free(brushData);
texture.id = texId;
texture.width = (int)width;
texture.height = (int)height;
return texture;
}
Demo下载地址
点击下载
网友评论