float4 CloudTechPS(CloudVS frg) : COLOR
{
float2 vUVMic = frg.texUV.xy * vMicroOff.zw + vMicroOff.xy;
float2 vUVTex = frg.texUV.xy;
// jarmonik: reduce microtex resolution
// vUVMic *= 0.5f; // new
float a = (tex2Dlod(NoiseTexS, float4(vUVTex,0,0)).r - 0.5f) * ATMNOISE;
float4 cTex = tex2D(DiffTexS, vUVTex);
float4 cMic = tex2D(CloudMicroS, vUVMic);
#if defined(_CLOUDNORMALS)
if (bCloudNorm) {
#if defined(_CLOUDMICRO)
float4 cMicNorm = tex2D(CloudMicroNormS, vUVMic); // Filename "cloud1_norm.dds" (does not exists in distribution)
#endif
// Filter width
float d = 2.0 / 512.0;
float3 nrm = 0;
float3 nrmMicro = 0;
float x1 = tex2D(DiffTexS, vUVTex + float2(-d, 0)).a;
float x2 = tex2D(DiffTexS, vUVTex + float2(+d, 0)).a;
nrm.x = (x1*x1 - x2*x2);
float y1 = tex2D(DiffTexS, vUVTex + float2(0, -d)).a;
float y2 = tex2D(DiffTexS, vUVTex + float2(0, +d)).a;
nrm.y = (y1*y1 - y2*y2);
float dMN = dot(frg.nrmW, vSunDir); // Planet mean normal sun angle
#if defined(_CLOUDMICRO)
// Blend in cloud normals only on moderately thick clouds, allowing the highest cloud tops to be smooth.
nrm.xy = (nrm.xy + saturate((cTex.a * 10.0f) - 3.0f) * saturate(((1.0f - cTex.a) * 10.0f) - 1.0f) * (cMicNorm.rg - 0.5f)); // new
#endif
// Increase normals contrast based on sun-earth angle.
nrm.xyz = nrm.xyz * (1.0f + (0.5f * dMN));
// jarmonik: saturate() added as a safety check
nrm.z = sqrt(1.0f - saturate(nrm.x*nrm.x + nrm.y*nrm.y));
// Approximate world space normal from local tangent space
nrm = normalize((vTangent * nrm.x) + (vBiTangent * nrm.y) + (frg.nrmW * nrm.z));
float dCS = dot(nrm, vSunDir); // Cloud normal sun angle
// Brighten the lighting model for clouds, based on sun-earth angle. Twice is better.
// Low sun angles = greater effect. No modulation leads to washed out normals at high sun angles.
dCS = saturate((1.0f - dMN) * (dCS * (1.0f - dCS)) + dCS);
dCS = saturate((1.0f - dMN) * (dCS * (1.0f - dCS)) + dCS);
// jarmonik: With a high sun angle, don't let the dCS go below 0.65f to avoid unnaturally dark edges.
dCS = lerp(0.2f*dMN, 1.0f, dCS);
// Effect of normal/sun angle to color
// Add some brightness (borrowing red channel from sunset attenuation)
// Adding it to the sun illumination factor, taking care to keep from saturating
cTex.rgb *= dCS + ((1.0f - dCS) * 0.2f);
}
#endif
#if defined(_CLOUDMICRO)
float f = cTex.a;
float g = lerp(1.0f, cMic.a, frg.fade.y);
float h = (g + 4.0f)*0.2f;
cTex.a = saturate(lerp(g, h, f) * f);
#endif
// Reduce attenuation near terminator (multiply by 3)
// Change attenuation to be grayscale, not colored (.r not .rgb)
// Ensure illumination goes as far as possible by borrowing red channel (.r)
float3 color = cTex.rgb*saturate(frg.atten.r * 3)*fCloudInts;
// Blend haze without saturating
color = lerp(color, 1.0f, frg.insca.rgb*vHazeMax);
return float4(saturate(color + a), cTex.a*saturate(fCloudInts*fCloudInts));
}