[url]http://bbs.9ria.com/viewthread.php?tid=79747&extra=page%3D1%26amp%3Borderby%3Ddateline%26amp%3Bfilter%3D2592000[/url]
试想有一天,人类灭亡。
试想在我们灭亡之后,所有纸质文档随着时间的推移,变得破旧且不能识别。
试想外星人找到了人类那些存储着有关人类信息的DVD或固态存储器。
他们将如何破译它?如何找到解读隐藏在这些“神器”中信息的密钥?
如果他们获取了我们的技术成果,他们如何能够真正理解我们的发现、使用我们的技术,是否他们需要这些技术自我解读呢?
Adobe最近推出了一种称为AGAL的新语言(Adobe Graphics Assembly Language)。它是Molehill的部件,其目的是为创建所谓的“着色器(shahers)”:影响三维模型在场景中如何渲染的微小程序。
这些着色器很酷,有着惊人的渲染效果,编写代码也比常规的AS更难。
AGAL看起来像这样:
是不是看着像天书?那使用它的关键是什么?
问题是现阶段AGAL的相关文档还很少。我来试着讲解这种神秘的着色语言。
The OpCode 操作码
着色器的每一行是一个由被称为“操作码(opcode)”的3个字符的字符串指定的命令行。
AGAL的代码语法如下:
<opcode> <destination> <source 1> <source 2 or sampler>
复制代码
<操作码> <目标> <来源1> <来源2或样例>
这很关键。记住此语法AGAL就不再像是一个不可读的二进制字符串了。
在操作码之后,根据该命令还可以有目标,以及一个或两个来源。目标和来源是“寄存器”:即供着色器使用的小块GPU内存区(以下更多的寄存器)。
AGAL有大约30种不同功能的操作码。在Molehill的文档中有操作码的完整列表。下面是一些最常见的操作码。
mov move data from source1 to destination, component-wise
add destination = source1 + source2, component-wise
sub destination = source1 – source2, component-wise
mul destination = source1 * source2, component-wise
div destination = source1 / source2, component-wise
dp3 dot product (3 components) between source1 and source2
dp4 dot product (4 components) between source1 and source2
m44 multiplication between 4 components vector in source1 and 4×4 matrix in source2
tex texture sample. Load from texture at source2 at coordinates source1.
AGAL Registers 寄存器
寄存器是GPU中的小块内存区域,供AGAL程序(着色器)执行时使用。寄存器即可用于AGAL命令的来源,也可用于目标。
你也可通过寄存器向着色器传递参数。
每个寄存器为128位,能包含4个浮点数值。每一个值被称为寄存器的组件。
寄存器组件可以通过“坐标”存取器(xyzw)和色彩存取器(rgba)存取。
所以,寄存器的第一个组件,既可以存取:
<register name>.x
也可以存取:
<register name>.r
上面的一些操作码,像“add”,执行他们的操作“智能组件”。意味着加法操作是按组件到组件执行的。
这是6个可用的寄存器类型。
1. Attribute Registers 属性寄存器
这些寄存器涉及顶点着色器的输入VertexBuffer。因此,他们只可用在顶点着色器。
为了指派一个VertexBuffer到指定的属性寄存器,在这个函数中使用正确的索引号Context3D::setVertexBufferAt()。
从着色器中访问该属性寄存器的语法:va<n>,其中<n>是属性寄存器的索引号。
总共有8个用于顶点着色器的属性寄存器。
2. Constant Registers 常量寄存器
这些寄存器是为了从ActionScript传递参数到着色器。通过Context3D::setProgramConstants()函数完成。
从着色器中访问这些寄存器的语法:vc<n>,用于顶点着色器,fc<n>,用于像素着色器,其中<n>是常量寄存器的索引号。
有128个用于顶点着色器和28个用于像素着色器的常量寄存器。
3. Temporary Registers 临时寄存器
这些寄存器供着色器在临时计算时使用。
访问它们的语法:vt<n>(点)和 ft<n> (像素),其中<n>是寄存器的序号。
有8个可用于顶点着色器,8个可用于像素着色器。
4. Output Registers 输出寄存器
输出寄存器存储顶点和像素着色器的计算输出。对于顶点着色器是一个顶点剪辑空间的位置。对于像素着色器是该像素的颜色。
访问这些寄存器的语法:op,用于顶点着色器,oc,用于像素着色器。
显然只有一个用于顶点和像素着色器的输出寄存器。
5. Varying Registers 变量寄存器
这些寄存器用来从顶点着色器向像素着色器传递数据。
这些寄存器用来传递从顶点着色器到像素着色器的数据。所传数据被GPU转换,从而使像素着色器接收到正确的值,用于正在处理的像素。
用这种方法传递的典型数据是顶点的颜色或纹理的UV坐标。
访问这些寄存器的语法:v<n>,其中<n>是寄存器序号。
有8个变量寄存器可用。
6. Texture Samplers 纹理采样寄存器
纹理采样寄存器是用来接收从基于UV坐标系的纹理中的颜色值。
纹理的指定通过ActionScript使用方法 Context3D::setTextureAt()。
纹理采样的使用语法是:ft<n> <flags>,其中<n>是采样序号,<flags>是一个或多个用于指定应如何取样的标志集。
<flags>是一个以逗号分隔的字符串集,其定义是:
纹理维度。可以是:2d, 3d, cube
多重材质映射。可以是:nomip, mipnone, mipnearest, mipnone
纹理滤镜。可以是:nearest, linear
重复纹理。可以是:repeat, wrap, clamp.
好了,举例来说,一个标准的没有多重材质映射的2D纹理,进行线性滤镜采样到临时寄存器ft1中,用下行:
其中变量寄存器v0保存以内插值替换的纹理UV坐标。
顶点和像素着色器例子解释
现在我们返回到着色器的例子,并解释其运作。
我们假设顶点在VertexBuffer中包含着顶点的位置,偏移量是0,纹理的UV偏移量是3。
我们希望我们的顶点着色器转换顶点位置到剪辑空间里,并传递UV到像素着色器。
执行以下代码:
第一行执行了在输入顶点,va0,和从模型空间到剪辑空间的变换矩阵之间的4×4矩阵乘法,我们假定已从ActionScript写入到常量寄存器0中,vc0。
用下面的方法可将此矩阵写入到着色器:
着色器的第二行,复制顶点UV数据到变量寄存器0,V0,因此,它可以获得修正,并传递到像素着色器。
像素着色器采样纹理,并复制颜色到输出寄存器。
tex ft1, v0, fs0 <2d,linear,nomip>
mov oc, ft1
复制代码
好了,这个顶点/像素着色器刚刚将三维模型转换到二维屏幕上,并进行了纹理映射。
这就是我们的第一个顶点和像素着色器!
真酷!那我现在可以制作一个着色器吗?
还不行!
其实,你可以制作着色器,但是无法使用,因为我们仍然会在Actionscript 这一面失败的。
在本教程的第二部分,我会深入到让ActionScript必须使用我们的着色器,并提供完整的演示代码。
我希望本教程对您有所帮助。如果是这样,请发表您的评论。
敬请关注!
试想有一天,人类灭亡。
试想在我们灭亡之后,所有纸质文档随着时间的推移,变得破旧且不能识别。
试想外星人找到了人类那些存储着有关人类信息的DVD或固态存储器。
他们将如何破译它?如何找到解读隐藏在这些“神器”中信息的密钥?
如果他们获取了我们的技术成果,他们如何能够真正理解我们的发现、使用我们的技术,是否他们需要这些技术自我解读呢?
Adobe最近推出了一种称为AGAL的新语言(Adobe Graphics Assembly Language)。它是Molehill的部件,其目的是为创建所谓的“着色器(shahers)”:影响三维模型在场景中如何渲染的微小程序。
这些着色器很酷,有着惊人的渲染效果,编写代码也比常规的AS更难。
AGAL看起来像这样:
//vertex shader 顶点着色器
m44 op, va0, vc0 // pos to clipspace
mov v0, va1 // copy uv
//pixel shader 像素着色器
tex ft1, v0, fs0 <2d,linear,nomip>
mov oc, ft1
是不是看着像天书?那使用它的关键是什么?
问题是现阶段AGAL的相关文档还很少。我来试着讲解这种神秘的着色语言。
The OpCode 操作码
着色器的每一行是一个由被称为“操作码(opcode)”的3个字符的字符串指定的命令行。
AGAL的代码语法如下:
<opcode> <destination> <source 1> <source 2 or sampler>
复制代码
<操作码> <目标> <来源1> <来源2或样例>
这很关键。记住此语法AGAL就不再像是一个不可读的二进制字符串了。
在操作码之后,根据该命令还可以有目标,以及一个或两个来源。目标和来源是“寄存器”:即供着色器使用的小块GPU内存区(以下更多的寄存器)。
AGAL有大约30种不同功能的操作码。在Molehill的文档中有操作码的完整列表。下面是一些最常见的操作码。
mov move data from source1 to destination, component-wise
add destination = source1 + source2, component-wise
sub destination = source1 – source2, component-wise
mul destination = source1 * source2, component-wise
div destination = source1 / source2, component-wise
dp3 dot product (3 components) between source1 and source2
dp4 dot product (4 components) between source1 and source2
m44 multiplication between 4 components vector in source1 and 4×4 matrix in source2
tex texture sample. Load from texture at source2 at coordinates source1.
AGAL Registers 寄存器
寄存器是GPU中的小块内存区域,供AGAL程序(着色器)执行时使用。寄存器即可用于AGAL命令的来源,也可用于目标。
你也可通过寄存器向着色器传递参数。
每个寄存器为128位,能包含4个浮点数值。每一个值被称为寄存器的组件。
寄存器组件可以通过“坐标”存取器(xyzw)和色彩存取器(rgba)存取。
所以,寄存器的第一个组件,既可以存取:
<register name>.x
也可以存取:
<register name>.r
上面的一些操作码,像“add”,执行他们的操作“智能组件”。意味着加法操作是按组件到组件执行的。
这是6个可用的寄存器类型。
1. Attribute Registers 属性寄存器
这些寄存器涉及顶点着色器的输入VertexBuffer。因此,他们只可用在顶点着色器。
为了指派一个VertexBuffer到指定的属性寄存器,在这个函数中使用正确的索引号Context3D::setVertexBufferAt()。
从着色器中访问该属性寄存器的语法:va<n>,其中<n>是属性寄存器的索引号。
总共有8个用于顶点着色器的属性寄存器。
2. Constant Registers 常量寄存器
这些寄存器是为了从ActionScript传递参数到着色器。通过Context3D::setProgramConstants()函数完成。
从着色器中访问这些寄存器的语法:vc<n>,用于顶点着色器,fc<n>,用于像素着色器,其中<n>是常量寄存器的索引号。
有128个用于顶点着色器和28个用于像素着色器的常量寄存器。
3. Temporary Registers 临时寄存器
这些寄存器供着色器在临时计算时使用。
访问它们的语法:vt<n>(点)和 ft<n> (像素),其中<n>是寄存器的序号。
有8个可用于顶点着色器,8个可用于像素着色器。
4. Output Registers 输出寄存器
输出寄存器存储顶点和像素着色器的计算输出。对于顶点着色器是一个顶点剪辑空间的位置。对于像素着色器是该像素的颜色。
访问这些寄存器的语法:op,用于顶点着色器,oc,用于像素着色器。
显然只有一个用于顶点和像素着色器的输出寄存器。
5. Varying Registers 变量寄存器
这些寄存器用来从顶点着色器向像素着色器传递数据。
这些寄存器用来传递从顶点着色器到像素着色器的数据。所传数据被GPU转换,从而使像素着色器接收到正确的值,用于正在处理的像素。
用这种方法传递的典型数据是顶点的颜色或纹理的UV坐标。
访问这些寄存器的语法:v<n>,其中<n>是寄存器序号。
有8个变量寄存器可用。
6. Texture Samplers 纹理采样寄存器
纹理采样寄存器是用来接收从基于UV坐标系的纹理中的颜色值。
纹理的指定通过ActionScript使用方法 Context3D::setTextureAt()。
纹理采样的使用语法是:ft<n> <flags>,其中<n>是采样序号,<flags>是一个或多个用于指定应如何取样的标志集。
<flags>是一个以逗号分隔的字符串集,其定义是:
纹理维度。可以是:2d, 3d, cube
多重材质映射。可以是:nomip, mipnone, mipnearest, mipnone
纹理滤镜。可以是:nearest, linear
重复纹理。可以是:repeat, wrap, clamp.
好了,举例来说,一个标准的没有多重材质映射的2D纹理,进行线性滤镜采样到临时寄存器ft1中,用下行:
“tex ft1, v0, fs0 <2d,linear,nomip> “
其中变量寄存器v0保存以内插值替换的纹理UV坐标。
顶点和像素着色器例子解释
现在我们返回到着色器的例子,并解释其运作。
我们假设顶点在VertexBuffer中包含着顶点的位置,偏移量是0,纹理的UV偏移量是3。
我们希望我们的顶点着色器转换顶点位置到剪辑空间里,并传递UV到像素着色器。
执行以下代码:
m44 op, va0, vc0 // pos to clipspace
mov v0, va1 // copy uv
第一行执行了在输入顶点,va0,和从模型空间到剪辑空间的变换矩阵之间的4×4矩阵乘法,我们假定已从ActionScript写入到常量寄存器0中,vc0。
用下面的方法可将此矩阵写入到着色器:
Context3D::setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true )
;
着色器的第二行,复制顶点UV数据到变量寄存器0,V0,因此,它可以获得修正,并传递到像素着色器。
像素着色器采样纹理,并复制颜色到输出寄存器。
tex ft1, v0, fs0 <2d,linear,nomip>
mov oc, ft1
复制代码
好了,这个顶点/像素着色器刚刚将三维模型转换到二维屏幕上,并进行了纹理映射。
这就是我们的第一个顶点和像素着色器!
真酷!那我现在可以制作一个着色器吗?
还不行!
其实,你可以制作着色器,但是无法使用,因为我们仍然会在Actionscript 这一面失败的。
在本教程的第二部分,我会深入到让ActionScript必须使用我们的着色器,并提供完整的演示代码。
我希望本教程对您有所帮助。如果是这样,请发表您的评论。
敬请关注!