翻译:弹涂鱼
PS:欢迎加入开发群:285275050
第一次翻译这么长的教程,翻译中间部分时有些不耐烦,可能大家在看时不会太明了。后面及时调整了心态。以后尽量每周翻译一篇外文资料。
自从3d游戏的引入,着色器很可能是计算机图形学的一大进步。它使编程人员可以创建全新的特效,并且能控制屏幕上所显示的内容。如果你还没有用过着色器,读完此篇文章后你将会用到。
Cocos2D是当下最好ios游戏开发框架,值得庆幸的是cocos2D现在已经支持openg-es 2.0和着色器。本教程中,在Cocos2D的帮助下你将学会如何去创建和使用着色器。你将学习以下内容:
l
l
l
1.
2.
3.
这是一篇高级教程,所以需要一些先决条件。为了能知道本篇在讲什么,你需要以下基础知识:
l
l
l
最后,我将使用最新的xcode,请确保更新到最新版。
前言
在探索和使用着色器前,你需要cocos2d 2.x和确保xcode集成了cocos2d模板。然后创建一个cocos2d项目,步骤如下
@H_358_301@ 1.接下在你的项目中启用arc,尽管cocos2d没有使用arc,你可以在余下的项目中去启用,这可以节约代码同时能减少内存泄露。
在菜单中选择Edit\Refactor\Convert to Objective-C ARC…。在代开的对话框中选中select main.m,AppDelegate.m and HelloWorldLayer.m
很简单吧?现在你可以在使用arc的同时感受cocos2d的力量。
编译运行,你会看到:
由于本教程中你不会用到高清图片,如果你的程序运行在高清显示屏上,你可能想禁用高清图片加载。找到AppDelegate.m把下面代码注释掉:
if( ! [director_ enableRetinaDisplay:YES] )
现在,准备工作完成,可以你的Cocos2D和着色器旅程了。
什么是着色器?
着色器是一个简单的类C程序,用于执行渲染特效。举例来说,正如名字所暗示的,着色器最基本的功能可能是为一个对象添加不同的色彩(或者是对象的一部分).
着色器程序在GPU(图形处理器)执行。对于移动设备,共有两类着色器:
上述两类着色器不能单独使用:它们必须同时出现。两类着色器组合在一起成为一个程序。它们这样来运行:
@H_358_301@ 1.在引入着色器以前,当你渲染特效时,你只能去调用已知的固定功能管道线。固定功能管道线允许你渲染那些差不多是硬件编码的特效。你可以去更改参数(修改颜色,位置等),这些也是你唯一能做的。
固定功能管道线的种种限制促进了着色器的诞生,着色器可以使你通过编程的方式去创建新的渲染特效。通常,着色器可以实现你能想到的所有特效:着色器可以使你去编写屏幕每次绘制时调用的程序。
Opengl-ES 2着色器使用OpenGL Shading Language,
(老外写的太细致了)
如何构建在Cocos2D中工作的着色器?
Cocos2d 2.x使用Opengl-es 2.0进行图形渲染,这样,即使是最简单的渲染你都需要着色器。所以每一个CCNode节点都有一个shaderProgram实例变量,这个实例变量保留了shader program的指针,当节点绘制时会被调用。
Cocos2D也提供了自己的CCShaderCache允许你调用默认的着色器程序,或者你也可以缓存自己的着色器程序,这样就能避免多次重复加载问题,你可以在libs\cocos2D\CCGLProgram.h找到访问预定义着色器的常量定义关键字。你可以在libs\cocos2d\ccShader_xxx.h.找到cocos2d使用的着色器。
下面这段代码是一个示例着色器程序:
在开始讲解这段代码之前,我们先来对shader有个大致了解,和它实现的目标。
每个着色器都需要输入值,并产生输出值。对于上面的着色器。
l
l
现在你已经有了大致了解,接下来进行更详细的分步介绍:
@H_358_301@ 1.下面是上述顶点着色器的片元着色器:
记住当执行到片元着色器时,opengl会为组成精灵的每一个像素时调用一次这个程序。这个程序的目的是为了表示出如何去为每一个像素着色。对这个默认着色器的回答很简单,仅仅是挑选出纹理中正确的点去匹配对应像素。
下面是分步介绍:
@H_358_301@ 1.在使你明白如何和把他们组合在一起前还有许多步要走,这些纹理正好在CCGrid.m中用到了,好的,打开文件看看如何使用。
首先,在init方法中shader从cache中加载
如果你感到好奇,妮可以在CCShaderCache中查看shaders是如何被编译和存储的。
接下来在blit方法中,向着色器材传入变量并运行。
你可能想知道纹理是在那里传入的呢?这里有个捷径—如果你不设置变量,他的默认值是0,另外第一个纹理的单元也是0,所以在afterDraw中绑定纹理,并且不用再次传入。
现在你已经学习了一个在cocos2d中使用纹理的实例,你可能想去深入挖掘CCSprite是如何渲染它自己的。
当你去做那件事时,充分分析。
是时候创建属于你自己的纹理了。
如何创建自己的着色器
大多数2D游戏有精灵组成,每个精灵有四个顶点。仅仅有这些还是不够,大多数2D特效是由片元着色器创建的。你即将使用cocos2d默认的顶点着色器来添加一个新的自定义片元着色器。
这里的目的是创建一个简单效果,在这里你将使用第二纹理去修改原始纹理颜色。你将使用“ramp”纹理(“ramp”texture)来操纵原始纹理。这是一个可以用与创建皮肤或卡通着色的效果。
下面是我们将要用到的纹理:
我们将处理颜色的三部分(r,g,b),它们被表述成0-1的百分比,如果你在使用0-255的范围表示,不要忘记除以255.
注意图片是如何从白(RGB 0.0,0.0,0.0)
(下面的不翻译了,相信你明白他在说什么)
所以,由于上图只有64像素宽,相对于原始图像它有较小的颜色变化范围,这导致了带状果。
好吧,让我们来试一下。你可能刚刚运行程序时就已经注意到,现在你有两个菜单选项--Achievements和Leaderboards。由于不需要Achievements和Leaderboards来处理纹理,所以你需要修改一下程序菜单,使它导航到着色器测试界面。
创建一个继承自CCLayer类,命名为CSEColorRamp。
打开HelloWorldLayer.m引入CSEColorRamp的头文件
#import "CSEColorRamp.h"
替换HelloWorldLayer中init方法为:
编译运行,你将看到
点击
打开CSEColorRamp替换@implementation
我们只是添加了一些私有变量。
@H_358_301@ 1.替换init方法为:
你都做了些什么?
@H_358_301@ 1.现在需要片元着色器来使这个层来工作。
创建一个新的空文件iOS\Other\Empty template,命名为CSEColorRamp.fsh,选择文件位置,将CocosShaderEffects从targets列表中移除点击create.移除的原因是它不是源码文件。而是资源(Xcode by default would add it to the Compile Sources phase).
现在你需要将新添加的片元着色器添加到Copy Bundle Resources build phase(省略详细)
修改CSEColorRamp.fsh如下:
注意:为增加上述代码可读性,在菜单中选择Editor/Syntax Coloring/GLSL,将会开始着色器语法颜色显示。
上述代码做了些什么?
@H_358_301@ 1.运行程序你会看到:
Cocos2d只是改变了他的皮肤颜色。
你可以尝试改变绑定的颜色图片来达到不同效果。减小图片宽度,将会有较小的颜色范围,这可以用于卡通着色。
创建浮雕着色器
是时候创建新的着色器了。
1.
自定义着色器来创建特别酷的特效(译)" title="cocos2d
3.
修该CSEEmboss.fsh如下
上述代码实现了什么:
1.
2.
3.
4.
5.
运行程序:
添加动作
那确实很cool,那么我们给这个浮雕效果添加一些动作怎么样?
打开CSEEmboss.m,移除与ramp texture有关的两个变量,
你需要uniform location,添加以下几行到init方法中(替换当前的3-5)
上述代码获取了时间值的uniform location,并且加入到cocos2d的update循环(每帧需要调用的函数)
上述代码每次更新时增加totalTime的值,并把它传给你自定义的着色器。调用时使用glUniform1f,因为你只传递了一个float值。
现在来修改一下你的CSEEmboss.fsh着色器,以便使用传入的uiniform类型的u_time。为了使用这个值来进行移动,你可以使用的最简单函数是基于u_time的sine/cosine。替换#3部分的代码为:
新的代码通过改变由texCoords所标识的坐标偏移来创建一个在-6到+6变化的波浪动作。
编译运行,选择Emboss menu你会看到一个浮雕化的cocos2d图标在移动。
简单动态的草
在最后,你将使用着色器来创建一些简单动态的草,你可以把它用到你的cocos2d 2.x游戏中。
使用iOS\cocos2d v2.x\CCNode模板类创建一个新的文件,使其继承CCLayer并命名为CSEGrass.m(如果你也复制@implementation这一行,不要忘记更改类名),在init方法中改变加载的片元着色器文件名为CSEGrass.fsh。
替换#1部分的代码为:
我们把代码改为使用草的纹理,由于草的纹理已经是横向状态,所以我们把rotation去掉。
接下来打开HelloWorldLayer.m
#import "CSEGrass.h"
添加一个新的片元着色器CSEGrass.fsh,添加步骤同上。
修改片元着色器为:
新的着色器是这样工作的以使草向一方弯曲,然后向另一方弯曲。这个弯曲影响操的顶部,而不是整个纹理。
以下是每一步的说明:
1.
2.
3.
4.
5.
编译运行程序:
翻译到此为止吧,后面还有一点无关紧要的,有兴趣的可以自己看英文的。