#pragma kernel EvaluateCloudMap #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" // #pragma enable_d3d11_debug_symbols CBUFFER_START(UnityCloudMapGenerator) int _CloudMapResolution; float _CumulusMapMultiplier; float _CumulonimbusMapMultiplier; float _AltostratusMapMultiplier; CBUFFER_END SamplerState linear_repeat_sampler; Texture2D _CumulusMap; Texture2D _CumulonimbusMap; Texture2D _AltostratusMap; Texture2D _RainMap; RWTexture2D _CloudMapTextureRW; #define ALTOSTRATUS_ONLY_RANGE_MIN (0.0f/256.0f) #define ALTOSTRATUS_ONLY_RANGE_MAX (32.0f/256.0f) #define ALTOSTRATUS_ONLY_MAX_HEIGHT 1.0f #define CUMULUS_ALTOSTRATUS_RANGE_MIN (32.0f/256.0f) #define CUMULUS_ALTOSTRATUS_RANGE_MAX (64.0f/256.0f) #define CUMULUS_ALTOSTRATUS_MAX_HEIGHT 1.0f #define CUMULUS_ONLY_RANGE_MIN (64.0f/256.0f) #define CUMULUS_ONLY_RANGE_MAX (128.0f/256.0f) #define CUMULUS_ONLY_MAX_HEIGHT 0.5f #define CUMULONIMBUS_RANGE_FIRST_MIN (128.0f/256.0f) #define CUMULONIMBUS_RANGE_SECOND_MIN (130.0f/256.0f) #define CUMULONIMBUS_RANGE_THIRD_MIN (136.0f/256.0f) #define CUMULONIMBUS_RANGE_MAX 1.0f #define CUMULONIMBUS_MAX_HEIGHT 1.0f float2 NormalizedCoordinates(uint2 coord) { return (coord + 0.5f) / _CloudMapResolution; } [numthreads(8, 8, 1)] void EvaluateCloudMap(uint2 currentCoord : SV_DispatchThreadID) { // If this pixel is not in the range, we are done if (any(currentCoord.xy >= (uint2) _CloudMapResolution)) return; // Compute the normalized coordinate of the current pixel float2 normalizedCoord = NormalizedCoordinates(currentCoord.xy); // Read all the cloud data float2 tapUV = float2(normalizedCoord.x, 1.0 - normalizedCoord.y); float cumulusCoverage = _CumulusMap.SampleLevel(linear_repeat_sampler, tapUV, 0) * _CumulusMapMultiplier; cumulusCoverage = cumulusCoverage < 0.01 ? 0.0 : cumulusCoverage; float cumulonimbusCoverage = _CumulonimbusMap.SampleLevel(linear_repeat_sampler, tapUV, 0); cumulonimbusCoverage = cumulonimbusCoverage < 0.01 ? 0.0 : cumulonimbusCoverage; float altoStratusCoverage = _AltostratusMap.SampleLevel(linear_repeat_sampler, tapUV, 0) * _AltostratusMapMultiplier; altoStratusCoverage = altoStratusCoverage < 0.01 ? 0.0 : altoStratusCoverage; float cloudRain = _RainMap.SampleLevel(linear_repeat_sampler, tapUV, 0); float cloudCoverage = 0.0; float cloudType = 0.0; float cloudMaxHeight = 0.0; // Cumulonimbus clouds have precedence over all the other clouds if (cumulonimbusCoverage * _CumulonimbusMapMultiplier > 0.0) { cloudType = cumulonimbusCoverage * (CUMULONIMBUS_RANGE_MAX - CUMULONIMBUS_RANGE_FIRST_MIN) + CUMULONIMBUS_RANGE_FIRST_MIN; if (cloudType < CUMULONIMBUS_RANGE_SECOND_MIN) { cloudCoverage = 0.0f; cloudMaxHeight = 0.0; } else if (cloudType < CUMULONIMBUS_RANGE_THIRD_MIN) { cloudCoverage = lerp(0.0, _CumulonimbusMapMultiplier, (cloudType - CUMULONIMBUS_RANGE_SECOND_MIN) / (CUMULONIMBUS_RANGE_THIRD_MIN - CUMULONIMBUS_RANGE_SECOND_MIN)); cloudMaxHeight = lerp(0.0, 1.0, (cloudType - CUMULONIMBUS_RANGE_SECOND_MIN) / (CUMULONIMBUS_RANGE_THIRD_MIN - CUMULONIMBUS_RANGE_SECOND_MIN)); } else { cloudCoverage = lerp(0.0, 0.75, _CumulonimbusMapMultiplier); cloudMaxHeight = 1.0f; } } // Cumulus have precedence over stratus else if (cumulusCoverage > 0.0) { if (altoStratusCoverage > 0.0) { cloudType = 0.5 * (CUMULUS_ALTOSTRATUS_RANGE_MAX - CUMULUS_ALTOSTRATUS_RANGE_MIN) + CUMULUS_ALTOSTRATUS_RANGE_MIN; cloudCoverage = max(cumulusCoverage, altoStratusCoverage); cloudMaxHeight = CUMULUS_ALTOSTRATUS_MAX_HEIGHT; } else { cloudType = 0.5 * (CUMULUS_ONLY_RANGE_MAX - CUMULUS_ONLY_RANGE_MIN) + CUMULUS_ONLY_RANGE_MIN; cloudCoverage = cumulusCoverage; cloudMaxHeight = CUMULUS_ONLY_MAX_HEIGHT; } } else { if (altoStratusCoverage > 0.0) { cloudType = 0.5 * (ALTOSTRATUS_ONLY_RANGE_MAX - ALTOSTRATUS_ONLY_RANGE_MIN) + ALTOSTRATUS_ONLY_RANGE_MIN; cloudCoverage = altoStratusCoverage; cloudMaxHeight = ALTOSTRATUS_ONLY_MAX_HEIGHT; } else { // No clouds were found cloudCoverage = 0.0f; cloudType = 0.0f; cloudMaxHeight = 0.0f; } } _CloudMapTextureRW[currentCoord] = float4(cloudCoverage, cloudRain, cloudType, cloudMaxHeight); }