Procedural Volumetric Shader HLSL

This shader is developed to create procedural volumetric effects using HLSL. It simulates the effect of wind on a texture by blending two different wind directions and speeds. The shader dynamically alters the texture’s appearance based on time, local position, and various parameters to achieve a realistic wind-blown effect.

  • Wind Direction and Speed: The shader uses two wind directions and speeds to simulate the effect of wind on the texture. The directions are represented by windDir_A and windDir_B, and the speeds by windSpeed_A and windSpeed_B.
  • UV Calculation: The UV coordinates for texture sampling are calculated based on the wind directions, speeds, and tiling factors. This creates the illusion of the texture being affected by the wind.
  • Flattening Effect: The flatten variable controls the flattening effect based on the height of the position within the bounds. This is used to reduce the density effect at higher positions.
  • Density Calculation: The densities are sampled from two textures and combined with a flattening effect. The result is used to influence the final color.
  • Color Blending: The final color is blended between two predefined colors (color_A and color_B) based on the calculated density and color gradient.
  • Extinction: The extinction value is calculated based on the density and can be used for further processing or effects in the shader.
// global Inputs
localPosition;    // Local position of the vertex/fragment
localBoundsMin;   // Minimum bounds of the local space
localBoundsSize;  // Size of the local bounds

// Wind direction and speed settings
float3 windDir_A = float3(1, 0, 0);
float3 windDir_B = float3(-1, 0, 0);
float windSpeed_A = 0.3;
float windSpeed_B = 0.1;

// Tiling factors for the wind effect
float tiling_A = 1;
float tiling_B = 3;

// Flattening and color gradient factors
float flatten = 1.5;
float colorGradient = 0.1;

// Colors for blending
float3 color_A = float3(0.6, 0.3, 0.2);
float3 color_B = float3(0.7, 0.7, 0.5);

// Convert local position to a bounded 3D space and zero out the z component
float3 bound3d = localPosition * 0.01;
bound3d.z = 0;

// Calculate UV coordinates for texture sampling based on wind direction, speed, and tiling
float3 uvA = (windDir_A * windSpeed_A * time) + (bound3d * tiling_A);
float3 uvB = (windDir_B * windSpeed_B * time) + (bound3d * tiling_B);

// Normalize the local position within the bounds and calculate the flattening effect
float3 flatten3d = (localPosition - localBoundsMin) / localBoundsSize;
float flatten1d = flatten3d.b * flatten;

// Sample densities from two textures using the calculated UV coordinates
float3 density_A = Texture2DSample(textureObj_A, textureObj_ASampler, uvA);
float3 density_B = Texture2DSample(textureObj_B, textureObj_BSampler, uvB);

// Compute the combined density with flattening effect and saturate the result
float density = ((1 - saturate(flatten1d / density_A)) / density_B);

// Calculate the base value for color blending
float colorBlendBase = max(density - colorGradient, 0.01);

// Smoothstep function to blend the color based on flattening effect
float colorBlend = smoothstep((colorBlendBase - 1), colorBlendBase, flatten1d);

// Linearly interpolate between two colors based on the blended value
float3 color = lerp(color_A, color_B, colorBlend);

// Set extinction value based on density (for further processing or effects)
extinction = density * 4;

// Return the final color
return float3(color);

REF: local volumetric fog by Ben Cloward>

Leave a comment