FunctiongetCloudColor(viewVector, // Direction of gazeskyColor, // Background sky colorbasePos, // Ray originsamples, // Number of samplesumbral, // Threshold used to remove low noisebrightFactor, // High light intensitydither, // Jitter parametersCLOUD_PARAMS// Various cloud layer constants such as plane, center, and thickness):// 1. If your gaze is downward, return directly to the sky color.ifviewVector.y ≤ 0:returnskyColor// 2. Calculate the intersection points t0 and t1 of the ray with the upper and lower cloud planes.t0 = (CLOUD_BOTTOM - basePos.y) / viewVector.yt1 = (CLOUD_TOP - basePos.y) / viewVector.y// 3. Generate the sampling start point p and step size stepVp = basePos + viewVector * t0pEnd = basePos + viewVector * t1stepV = (pEnd - p) / samplesp += stepV * dither// Add a small amount of jitter to reduce banding// 4. Sample along the ray, accumulating "cloud thickness" cv and "first hit depth" dencv = 0// Cumulative cloud volume componentsden = 0// Relative position upon first entry into the cloud layer (0~1)firstHit = truetotalRange = (CLOUD_CENTER - CLOUD_BOTTOM) + (CLOUD_TOP - CLOUD_CENTER)foriin0 .. samples-1:// 4.1 Sampling noise (height field)noiseHi = sampleNoiseHeight(p.xz, timeOffsetHigh)noiseLo = sampleNoiseHeight(p.zx, timeOffsetLow) // Optional multi-layer mixingnoise = mixAndSmooth(noiseHi, noiseLo)// 4.2 Calculate the upper and lower boundaries of the cloud layer based on the thresholdv = (noise - umbral) / (1 - umbral)inf = CLOUD_CENTER - v * (CLOUD_CENTER - CLOUD_BOTTOM)sup = CLOUD_CENTER + v * (CLOUD_TOP - CLOUD_CENTER)// 4.3 Determine if the current sampling point py is inside the cloud layerifinf < p.y < sup:cv += min(stepLength, sup - inf)iffirstHit:den = (sup - p.y) / totalRangefirstHit = falseelseifwithinSoftEdge(p.y, inf, sup, CLOUD_EDGE_WIDTH):// Edge transition: Add a little accumulation softlycv += softBlendAmount(p.y, inf, sup) iffirstHit:den = (sup - p.y) / totalRangefirstHit = falsep += stepV// 5. Normalized cumulative value and depthopacity = clamp(cv / (2 * CLOUD_EDGE_WIDTH / viewVector.y), 0, 1)density = clamp(den, 0.0001, 1)// 6. Select colors by density: Low—Medium—Highifdensity < 0.33:baseColor = COL_SH// Cloud backgroundelseifdensity < 0.66:baseColor = COL_MD// Mid-layer colorelse:baseColor = COL_HI// Cloud Top Color// 7. Viewpoint Highlights: Only high-density areas are highlighted.ifdensity > 0.66:highlight = dot(computeNormal(density), -viewVector)baseColor = Mix(baseColor, COL_HI, highlight * brightFactor)// 8. Self-shadow: The thicker the shadow, the darker it is.baseColor *= Mix(1.0, 0.85, density^2 * 0.5)// 9. Edge Stroke: Enhance the contour based on the depth field gradientedgeFactor = computeEdgeFactor(opacity)baseColor = Mix(baseColor, OUTLINE_COLOR, edgeFactor * 0.3)// 10. Adjust the darkness at night according to the brightness of the sky.nightFactor = computeNightFactor(skyColor)baseColor *= nightFactor// 11. Final blend: Cloud-covered backgroundalpha = opacity * clamp((viewVector.y - 0.05) * 5.0, 0, 1)returnMix(skyColor, baseColor, alpha)
Leave a Reply