后處理掃光是很早之前為大場景制作的后處理效果,也在群里吸取了很多群友的意見不斷完善顯示效果。這是一個比較簡單但是思想上比較基礎(chǔ)泛用的后處理效果,以此舉一反三可以制作很多種類的效果。本文最終的PG路徑:。
步驟規(guī)劃
想要制作掃光后處理,我們只需要做三件事情:
- 深度重建世界坐標。
- 通過世界坐標計算掃光的前進軸x軸和與前進軸垂直的等勢軸y軸。
- 根據(jù)前進軸的x軸和y軸繪制出顏色效果。
具體步驟
- 深度重建世界坐標的過程已經(jīng)在BabylonJS后處理系列: 深度基礎(chǔ)中介紹過了,這里將在BabylonJS后處理系列: 深度基礎(chǔ)的PG的基礎(chǔ)上繼續(xù)制作。PG
- 這一步先以水平掃光舉例,我們添加一個角度控制掃光的方向,然后用下列的函數(shù)變幻出前進軸和等勢軸。PG
vec2 getScanAxis(vec3 wPos){
float angle = scanAngle/180.*PI;
vec2 sPos;
sPos.x = wPos.x*cos(angle)+wPos.z*sin(angle);
sPos.y = wPos.z*cos(angle)-wPos.x*sin(angle);
return sPos;
}
3.第三步根據(jù)前進軸進行Remap,然后繪制顏色。
//首先沿X軸按掃光間隔長度進行取余得到 frontLine 。
float frontLine = mod(axisPos.x-scanTime,scanLength);

//將frontLine歸1
float scanLine = frontLine/scanLength;

//根據(jù)Percent將frontLine平移縮放,使得只有Percent*長度的部分在X軸的上方,然后取大于0的值。
scanLine = max((scanLine-1.+scanPercent)/scanPercent,0.);

這樣我們就獲取到了一個寬占掃光間隔長度百分之N的范圍為0-1的線性帶,這一條為掃光的顯示區(qū)域,我們可以以scanLine為X軸,等勢軸為y軸去計算顯色區(qū)域或采樣紋理等,這個可以自由發(fā)揮。PG
//求前沿高亮部分
float frontLineStep = step(scanLength-frontLine,frontLineWidth);
vec4 finColor ;
//獲取最終顏色
finColor.rgb = mix(scanColor*scanPower,frontColor,frontLineStep);
finColor.a = scanLine;

PG:https://playground.babylonjs.com/#KZP9WM#5
添加一個自定義TransformNode去控制參數(shù)(目前PostProcess的自定義控件好像有bug不顯示,只能創(chuàng)一個TransformNode去顯示)。詳見LightScanTransformNode。
簡單拓展
vec4 getScanColor(vec2 axisPos){
float scanX = axisPos.x +50. * (cos(axisPos.y/2./100.)+cos(axisPos.y/2./50.)+cos(axisPos.y/2./25.));
float frontLine = mod(scanX-scanTime,scanLength);
.........
}

2.掃描面采樣
float scanWidth = scanLength * scanPercent * 0.5;
float scanHeight = scanWidth*4.;
vec3 scanTexColor = texture2D(scanTex,vec2(max(scanLine*2.-1.,0.),axisPos.y/scanHeight)).rgb;
finColor.rgb = max(finColor.rgb,scanTexColor);

3.以圓心擴散掃光可以通過gizmo修改中心位置
vec2 getScanAxis(vec3 wPos){
float angle = scanAngle/180.*PI;
vec2 sPos;
// sPos.x = wPos.x*cos(angle)+wPos.z*sin(angle);
// sPos.y = wPos.z*cos(angle)-wPos.x*sin(angle);
vec2 dtPos = wPos.xz - centerTarget.xz;
sPos.x = length(dtPos);
sPos.y = atan(dtPos.y,dtPos.x);
return sPos;
}


