我自己解決了這個問題,在幾個小時的時間內進行了大量的試驗和錯誤嘗試。
因爲我只需要着色器在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;
}
希望這些提取出的代碼段可以幫助他人與類似着色器的問題。
祝你好運!