Actionscript 3 在Starling中,如何变换过滤器以匹配目标精灵';s旋转&;位置?
假设您的椋鸟显示列表如下:Actionscript 3 在Starling中,如何变换过滤器以匹配目标精灵';s旋转&;位置?,actionscript-3,flash,shader,fragment-shader,starling-framework,Actionscript 3,Flash,Shader,Fragment Shader,Starling Framework,假设您的椋鸟显示列表如下: Stage |___MainApp |______Canvas (filter's target) 然后,您决定将MainApp旋转90度并偏移一点: mainApp.rotation = Math.PI * 0.5; mainApp.x = stage.stageWidth; 但突然之间,过滤器继续以最初的角度将自身应用于目标(画布)(好像MainApp仍处于0度) (请注意,在GIF中,尽管父对象已旋转90度,但模糊的“强水平”值仍
Stage
|___MainApp
|______Canvas (filter's target)
然后,您决定将MainApp
旋转90度并偏移一点:
mainApp.rotation = Math.PI * 0.5;
mainApp.x = stage.stageWidth;
但突然之间,过滤器继续以最初的角度将自身应用于目标(画布)(好像MainApp仍处于0度)
(请注意,在GIF中,尽管父对象已旋转90度,但模糊的“强水平”值仍然仅在水平方向上应用)。
在目标对象获得其父对象变换之前,需要更改哪些内容才能将过滤器应用于目标对象?这样(我假设)过滤器的结果将被父对象转换
你猜怎么做
(注:我实际使用的过滤器是定制的,但这个BlurFilter示例显示了与定制过滤器相同的问题。如果着色器代码中有任何修补,至少不一定要在内置的BlurFilter上专门完成).我自己解决了这个问题,在几个小时的过程中进行了多次尝试和错误尝试 由于我只需要着色器以0或90度运行(与问题中显示的gif演示不同),因此我创建了一个具有两组专门AGAL指令的着色器 在不涉及太多细节的情况下,旋转版本基本上需要一些额外的指令来翻转顶点和片段着色器中的x和y字段(通过使用
mov
移动它们,或者直接将mul
或div
结果计算到x或y字段中)
例如,比较0度顶点着色器
_vertexShader = [
"m44 op, va0, vc0", // 4x4 matrix transform to output space
"mov posOriginal, va1", // pass texture positions to fragment program
"mul posScaled, va1, viewportScale", // pass displacement positions (scaled)
].join("\n");
。。。使用90度顶点着色器:
_vertexShader = [
"m44 op, va0, vc0", // 4x4 matrix transform to output space
"mov posOriginal, va1", // pass texture positions to fragment program
//Calculate the rotated vertex "displacement" UVs
"mov temp1, va1",
"mov temp2, va1",
"mul temp2.y, temp1.x, viewportScale.y", //Flip X to Y, and scale with viewport Y
"mul temp2.x, temp1.y, viewportScale.x", //Flip Y to X, and scale with viewport X
"sub temp2.y, 1.0, temp2.y", //Invert the UV for the Y axis.
"mov posScaled, temp2",
].join("\n");
您可以忽略AGAL示例中的特殊别名,它们基本上是posOriginal=v0,posScaled=v1
变量和viewportScale=vc4
常量,然后我进行字符串替换,将它们更改回各自的寄存器和字段)
这只是我用来避免发疯的一个人类可读的技巧<强>\☻/强>
我最费劲的部分是计算正确的比例来调整UV的比例(通过适当的检测来调整舞台/视口大小和渲染纹理大小的变化)
最终,我在AS3代码中得出了以下结论:
var pt:Texture = _passTexture,
dt:RenderTexture = _displacement.texture,
notReady:Boolean = pt == null,
star:Starling = Starling.current;
var finalScaleX:Number, viewRatioX:Number = star.viewPort.width / star.stage.stageWidth;
var finalScaleY:Number, viewRatioY:Number = star.viewPort.height / star.stage.stageHeight;
if (notReady) {
finalScaleX = finalScaleY = 1.0;
} else if (isRotated) {
//NOTE: Notice how the native width is divided with height, instead of same side. Weird, but it works!
finalScaleY = pt.nativeWidth / dt.nativeHeight / _imageRatio / paramScaleX / viewRatioX; //Eureka!
finalScaleX = pt.nativeHeight / dt.nativeWidth / _imageRatio / paramScaleY / viewRatioY; //Eureka x2!
} else {
finalScaleX = pt.nativeWidth / dt.nativeWidth / _imageRatio / viewRatioX / paramScaleX;
finalScaleY = pt.nativeHeight / dt.nativeHeight / _imageRatio / viewRatioY / paramScaleY;
}
希望这些提取的代码片段能够对其他具有类似着色器问题的人有所帮助
祝你好运