Table of contents
Introduction
This snippet allows to add a simple turbulence effect to the ribbon trails.
Usage
Just add a reference to the shader in your ribbon material and you're done.
There are several parameters to control the effect:
- curlSize, float:
- The "size" (radius, diameter... not really any of them but rather similar) of the turbulence curls.
- gravity, float3:
- A constant force applied to the vertices. For instance, windy environments would have strong horizontal components, and fire would have a strong vertical component.
- ttl, float:
- A time scale. Age is calculated in the shader as a value in the range 0, 1. This parameter tells how much "time" age=1 means.
- seed, float3:
- Just three simple numbers to displace the turbulence.
- amount, float:
- How much the trail will be affected by the turbulence.
Note that the example shader uses the vertex colour alpha to determine its age. Different approaches would require to tweak the shader (for instance, using texture coordinates instead).
The files
RibbonTurbulence.cg:
void ribbon_turbulence_vp (float4 position : POSITION, float3 normal : NORMAL, float2 uv : TEXCOORD0, float4 col : COLOR, out float4 oPosition : POSITION, out float2 oUv : TEXCOORD0, out float4 oCol : COLOR, uniform float4x4 worldViewProj, uniform float curlSize, uniform float3 gravity, uniform float ttl, uniform float3 seed, uniform float amount) { float4 mypos = position; float3 deviation = position.xyz; float age = (1 - col.a) * ttl; mypos.xyz += gravity * age; // Calculate some simple turbulence deviation = sin ((deviation + seed) / curlSize) * age * amount; mypos.xyz += deviation; oPosition = mul(worldViewProj, mypos); oUv = uv; oCol = col; }
The example ribbon trail material tweaked to use this shader:
vertex_program RibbonTurbulenceVp cg { source RibbonTurbulence.cg entry_point ribbon_turbulence_vp profiles vs_1_1 arbvp1 vp20 default_params { param_named_auto worldViewProj worldviewproj_matrix param_named curlSize float 3.5 param_named gravity float3 0 30 0 param_named ttl float 1 param_named seed float3 123 -456 789 param_named amount float 20 } } material Examples/LightRibbonTrail { technique { pass { vertex_program_ref RibbonTurbulenceVp { } lighting off scene_blend add depth_write off cull_hardware none cull_software none texture_unit { texture ribbonband.png 1d tex_address_mode clamp filtering none } } } }
Closing note
There's a video of this effect working here.
Thanks for reading. Hope you find it useful!
Tweaking
The shader presented above works best when the object is moving in random directions (i.e. not in a straight line). It may be more suitable to use the textures coordinates instead of the position to calculate a "random" disturbance. I will demonstrate how to do that in this section which will hopefully help you understand how it works and then allow you to make your own modifications. For this to work, the v texture coordinate must increase linearly along the length of the ribbon trail.
void ribbon_turbulence_vp (float4 position : POSITION, float3 normal : NORMAL, float2 uv : TEXCOORD0, float4 col : COLOR, out float4 oPosition : POSITION, out float2 oUv : TEXCOORD0, out float4 oCol : COLOR, uniform float4x4 worldViewProj, uniform float curlSize, uniform float3 gravity, uniform float ttl, uniform float seed, uniform float amount) { float4 mypos = position; float age = (1 - col.a) * ttl; mypos.xyz += gravity * age; mypos.x += cos((seed+uv.v)/curlSize) * age * amount; mypos.z += sin((seed+uv.v)/curlSize) * age * amount; oPosition = mul(worldViewProj, mypos); oUv = uv; oCol = col; }
Now the trail has a rotating motion in the XZ plane, you can of course modify this to create movement in whatever plane you like or use more complex equations to create some other type of movement that may be suitable for your application.
Alias: Smoke_Trails