原计划是丢HDR效果的,但是实际上HDR效果中要用到Blur效果的,因此先丢Blur
模糊效果是后期效果中比较简单效果. 这里不做径向模糊,不做正态分布,纯粹的模糊就是将当前像素的颜色以周围的像素为平均值来求出.
根据这个原理,当拿到uv值时,只需要做一次3*3的遍历,来求出周围8个像素,然后将像素叠加/8即可获得平均值,剩下的事就是用AGAL来求出了.
不上图了,做个代码笔记,之后就是Demo
周围像素的数量为圈数 n – 1 * 3 * 24, 其中 n > 1; 当 n 小于等于 1时. 像素的数量为8
整理为代码就是
var index : uint = step <= 1 ? 1 : (step - 1) * 3;
var num : uint = 8 * index;
之后我们需要用拼接的方式来构造AGAL
[cc lang="actionscript3"]
private function getBlurAgal(step : uint, force : uint, coord : String, pTempIndex : int, pSaveIndex : int, pConstantOffset : int, pTextureIndex : int, constant : Vector.
{
var data : Array = new Array();
var isFirstSave : Boolean = true;
var loopNum : uint = 0;
var stepX : Number = force / stage.stageWidth;
var stepY : Number = force / stage.stageHeight;
var index : uint = step <= 1 ? 1 : (step - 1) * 3;
var num : uint = 8 * index;
var tempIndex : int = pTempIndex;
var saveIndex : int = pSaveIndex;
var textureIndex : int = pTextureIndex;
var initIndex : int = pInitIndex;
var constantOffset : int = pConstantOffset;
constant = constant || new Vector.
constant.length = 0;
data.push(“mov ft” + tempIndex + “, fc” + initIndex);
//横向遍历
for(var i : int = -step; i <= step; i++)
{
//纵向遍历
for(var j : int = -step; j <= step; j ++)
{
//跳过中心区
if(i == 0 && j == 0) continue;
constant.push(i * stepX, j * stepY);
data.push("add ft" + tempIndex + ".xy, " + coord + ".xy, fc" + constantOffset + (loopNum % 2 == 0 ? ".xy" : ".zw"));
data.push("tex ft" + tempIndex + ", ft" + tempIndex + ", fs" + textureIndex + "<2d, repeat, linear, mipnone>“);
data.push(
isFirstSave ? “mov ft” + saveIndex + “, ft” + tempIndex :
“add ft” + saveIndex + “, ft” + saveIndex + “, ft” + tempIndex);
isFirstSave = false;
if(++loopNum % 2 == 0) constantOffset++;
}
}
data.push(“div ft” + saveIndex + “.rgb, ft” + saveIndex + “.rgb, fc” + constantOffset + “.w”);
data.push(“mov oc, ft” + saveIndex);
if(constant.length / 4 > 28){
return getBlurAgal(1,1,coord,pTempIndex,pSaveIndex,pConstantOffset,pTextureIndex,constant,pInitIndex);
}
constant.push(0,0,0,num);
return data.join(“n”);
}
[/cc]
var stepX : Number = force / stage.stageWidth;
var stepY : Number = force / stage.stageHeight;
求出当前屏幕大小纹理的u和v的步进值
data.push(“mov ft” + tempIndex + “, fc” + initIndex);
初始化用来保存周围像素的值的寄存器, 初始化值这里是 0,0,0,0
(loopNum % 2 == 0 ? “.xy” : “.zw”)
由于常量寄存器数量只有28个,因此如果每个float4 我们只有xy,那么zw就被浪费了,Blur的层级也无法提升,因此基于物尽其用的原则,每2个uv使用一个float4.
if(constant.length / 4 > 28)
由于常量寄存器只有28个, 其中每4个长度为一个 float4 因此当超过28个寄存器时,将模糊滤镜重置为最小滤镜
data.push(
isFirstSave ? “mov ft” + saveIndex + “, ft” + tempIndex :
“add ft” + saveIndex + “, ft” + saveIndex + “, ft” + tempIndex);
isFirstSave = false;
用来记录当前累加颜色的寄存器必须初始化,可以给它丢个initIndex中的值,但实际上这里直接把第一次的得出的颜色值mov进去就当作它的初始化值就够了,不需要额外的初始化.
使用方法:
var m_blurAgal : String = getBlurAgal(3, 1, “v0″, 0, 1, 1, 0, m_blurConstant, 0); fragmentProgram.assemble(Context3DProgramType.FRAGMENT, m_blurAgal);
初始化一个圈数为3,强度为1,uv位置为”v0”,纹理位置在0,常量偏移为1,临时寄存器为1,常量数组,初始值在常量位置1
编译agal
最后是Demo: click me
Github地址: click me