// fog related calculations //pos, cc_cameraPos.xyz, cc_fogBase.x, cc_fogBase.y float LinearFog(vec4 pos, vec3 cameraPos, float fogStart, float fogEnd) { vec4 wPos = pos; float cam_dis = distance(cameraPos, wPos.xyz); return clamp((fogEnd - cam_dis) / (fogEnd - fogStart), 0., 1.); } //pos, cc_cameraPos.xyz, cc_fogBase.x, cc_fogBase.z, cc_fogAdd.z float ExpFog(vec4 pos, vec3 cameraPos, float fogStart, float fogDensity, float fogAtten) { vec4 wPos = pos; float cam_dis = max(distance(cameraPos, wPos.xyz) - fogStart, 0.0) / fogAtten * 4.; float f = exp(-cam_dis * fogDensity); return f; } float ExpSquaredFog(vec4 pos, vec3 cameraPos, float fogStart, float fogDensity, float fogAtten) { vec4 wPos = pos; float cam_dis = max(distance(cameraPos, wPos.xyz) - fogStart, 0.0) / fogAtten * 4.; float f = exp(-cam_dis * cam_dis * fogDensity * fogDensity); return f; } //pos, cc_cameraPos.xyz, cc_fogAdd.x, cc_fogAdd.y, cc_fogAdd.z float LayeredFog(vec4 pos, vec3 cameraPos, float fogTop, float fogRange, float fogAtten) { vec4 wPos = pos; vec3 camWorldProj = cameraPos.xyz; camWorldProj.y = 0.; vec3 worldPosProj = wPos.xyz; worldPosProj.y = 0.; float fDeltaD = distance(worldPosProj, camWorldProj) / fogAtten * 2.0; float fDeltaY, fDensityIntegral; if (cameraPos.y > fogTop) { if (wPos.y < fogTop) { fDeltaY = (fogTop - wPos.y) / fogRange * 2.0; fDensityIntegral = fDeltaY * fDeltaY * 0.5; } else { fDeltaY = 0.; fDensityIntegral = 0.; } } else { if (wPos.y < fogTop) { float fDeltaA = (fogTop - cameraPos.y) / fogRange * 2.; float fDeltaB = (fogTop - wPos.y) / fogRange * 2.; fDeltaY = abs(fDeltaA - fDeltaB); fDensityIntegral = abs((fDeltaA * fDeltaA * 0.5) - (fDeltaB * fDeltaB * 0.5)); } else { fDeltaY = abs(fogTop - cameraPos.y) / fogRange * 2.; fDensityIntegral = abs(fDeltaY * fDeltaY * 0.5); } } float fDensity; if (fDeltaY != 0.) { fDensity = (sqrt(1.0 + ((fDeltaD / fDeltaY) * (fDeltaD / fDeltaY)))) * fDensityIntegral; } else { fDensity = 0.; } float f = exp(-fDensity); return f; }