https://github.com/keijiro/KinoFog
lighting box 2.7.2
halfspace fog 相機位於一個位置 這個位置可以在fog volumn里面或者外面 霧開始的地方就是文中的plane
http://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf
這個fog volume可以從中間某個位置height 這個平面產生霧 遠近濃度通過depth深度計算
還可以定義霧密度
// Applies one of standard fog formulas, given fog coordinate (i.e. distance) half ComputeFogFactor (float coord) { float fogFac = 0.0; if (_SceneFogMode.x == 1) // linear { // factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start)) fogFac = coord * _SceneFogParams.z + _SceneFogParams.w; } if (_SceneFogMode.x == 2) // exp { // factor = exp(-density*z) fogFac = _SceneFogParams.y * coord; fogFac = exp2(-fogFac); } if (_SceneFogMode.x == 3) // exp2 { // factor = exp(-(density*z)^2) fogFac = _SceneFogParams.x * coord; fogFac = exp2(-fogFac*fogFac); } return saturate(fogFac); } // Distance-based fog float ComputeDistance (float3 camDir, float zdepth) { float dist; if (_SceneFogMode.y == 1) dist = length(camDir); else dist = zdepth * _ProjectionParams.z; // Built-in fog starts at near plane, so match that by // subtracting the near value. Not a perfect approximation // if near plane is very large, but good enough. dist -= _ProjectionParams.y; return dist; } float ComputeHalfSpace (float3 wsDir) { float3 wpos = _CameraWS + wsDir; float FH = _HeightParams.x; float3 C = _CameraWS; float3 V = wsDir; float3 P = wpos; float3 aV = _HeightParams.w * V; float FdotC = _HeightParams.y; float k = _HeightParams.z; float FdotP = P.y-FH; float FdotV = wsDir.y; float c1 = k * (FdotP + FdotC); float c2 = (1-2*k) * FdotP; float g = min(c2, 0.0); g = -length(aV) * (c1 - g * g / abs(FdotV+1.0e-5f)); return g; }
FdocC = camPos.y-height.value; height 就是halfplane所定義的高度 plane法線垂直向上
// Calculate vectors towards frustum corners. var cam = GetComponent<Camera>(); var camtr = cam.transform; var camNear = cam.nearClipPlane; var camFar = cam.farClipPlane; var tanHalfFov = Mathf.Tan(cam.fieldOfView * Mathf.Deg2Rad / 2); var toRight = camtr.right * camNear * tanHalfFov * cam.aspect; var toTop = camtr.up * camNear * tanHalfFov; var v_tl = camtr.forward * camNear - toRight + toTop; var v_tr = camtr.forward * camNear + toRight + toTop; var v_br = camtr.forward * camNear + toRight - toTop; var v_bl = camtr.forward * camNear - toRight - toTop; var v_s = v_tl.magnitude * camFar / camNear; // Draw screen quad. RenderTexture.active = destination; _material.SetTexture("_MainTex", source); _material.SetPass(0); GL.PushMatrix(); GL.LoadOrtho(); GL.Begin(GL.QUADS); GL.MultiTexCoord2(0, 0, 0); GL.MultiTexCoord(1, v_bl.normalized * v_s); GL.Vertex3(0, 0, 0.1f); GL.MultiTexCoord2(0, 1, 0); GL.MultiTexCoord(1, v_br.normalized * v_s); GL.Vertex3(1, 0, 0.1f); GL.MultiTexCoord2(0, 1, 1); GL.MultiTexCoord(1, v_tr.normalized * v_s); GL.Vertex3(1, 1, 0.1f); GL.MultiTexCoord2(0, 0, 1); GL.MultiTexCoord(1, v_tl.normalized * v_s); GL.Vertex3(0, 1, 0.1f); GL.End(); GL.PopMatrix();
這里是用了一個quard我做到用trangle了
要銘記一點 quard 和trangle的插值結果 頂多數據傳對了 插值是一樣的 沒有差別 因為都是線性的 這個問題我想了好幾個小時!
uv 和pos肯定是一樣的 dir也是一樣的 因為也是線性的
這意味着我接下來可以做大面積優化了 好開心
mg你太棒了 這個小故事告訴我們代碼要每一行都看懂 不要再像黑盒那樣抄了
Vector3 topLeft3 = topLeft*2-bottomLeft;//2
Vector3 bottomRight3 = bottomRight*2 -bottomLeft;//1
Vector3 topRight3= bottomRight3+topLetf3;//0
這里因為scale過到farplane不能在原始那個nearplane的數據直接3x