struct HPS_VS_OUT { float4 hPosition : POSITION; float4 cPosition : TEXCOORD1; float2 texCoord : TEXCOORD0; float r : TEXCOORD2; float4 center : TEXCOORD3; float4 Color : TEXCOORD4; }; ////////////// ///This shader used when rendering an image of the small particle system of a HPS. ///It stores max distance from the camera in the red channel, one minus min distance in the green channel /// and the opacity in the alpha channel. ///////////// HPS_VS_OUT GTP_HPS_Small_VS (float4 position : POSITION, float4 texCoord : TEXCOORD0, float4 Color: COLOR0, uniform float4x4 worldView, uniform float4x4 Proj) { HPS_VS_OUT OUT; ///transform vertices to camera space and create a sprite float2 offset = texCoord.zw; float4 cPosition; cPosition = mul(worldView, position); OUT.center = cPosition; cPosition.xy += offset; OUT.cPosition = cPosition; OUT.r = abs(texCoord.z); ///projection OUT.hPosition = mul( Proj, cPosition ); OUT.texCoord = texCoord.xy; OUT.Color = Color; return OUT; } float4 GTP_HPS_Small_PS(HPS_VS_OUT IN, uniform float4x4 Proj, uniform sampler2D Texture ) : COLOR { float4 Color = 0; float f = 0; float b = 1; float alpha = 0; ///calculate back and front distances float d = length( IN.cPosition.xy- IN.center.xy); if( d < IN.r ) { float w = sqrt( IN.r * IN.r - d * d ); float4 fPosition = IN.cPosition; float4 bPosition = IN.cPosition; fPosition.z -= w; bPosition.z += w; fPosition = mul(Proj, fPosition); bPosition = mul(Proj, bPosition); f = fPosition.z / fPosition.w; b = bPosition.z / bPosition.w; // alpha = pow(w / IN.r, 4); } else discard; Color.r = b; Color.g = 1 - f; alpha = 1; Color.a = alpha * IN.Color.a; Color.a *= tex2D(Texture, IN.texCoord).r * 0.7; return Color; } ////////////// ///This shader renders a HPS, the image of the smaller system is passed to the fragment shader ///////////// HPS_VS_OUT HPS_Large_VS (float4 position : POSITION, float4 texCoord : TEXCOORD0, float4 Color: COLOR0, uniform float baseRadius, uniform float4x4 worldView, uniform float4x4 Proj) { ///transform vertices to camera space and create a sprite HPS_VS_OUT OUT; float2 offset = texCoord.zw * baseRadius; float4 cPosition; cPosition = mul(worldView, position); OUT.center = cPosition; cPosition.xy += offset; OUT.cPosition = cPosition; OUT.r = abs(offset.x); ///project OUT.hPosition = mul( Proj, cPosition ); OUT.texCoord = texCoord.xy; OUT.Color = Color; return OUT; } float4 HPS_Large_PS(HPS_VS_OUT IN, uniform sampler2D Texture ) : COLOR { float4 Color = 0; Color = tex2D(Texture, IN.texCoord); Color = float4(1, 1, 1, Color.a) * IN.Color; return Color; } ////////////// ///This shader renders a HPS with depth calculation, the scene distance map is passed to the fragment shader ///////////// struct HPS_DEPTH_VS_OUT { float4 hPosition : POSITION; float4 cPosition : TEXCOORD1; float2 texCoord : TEXCOORD0; float r : TEXCOORD2; float4 center : TEXCOORD3; float4 Color : TEXCOORD4; float2 screenCoord : TEXCOORD5; }; HPS_DEPTH_VS_OUT HPS_Large_Depth_VS (float4 position : POSITION, float4 texCoord : TEXCOORD0, float4 Color: COLOR0, uniform float baseRadius, uniform float4x4 worldView, uniform float4x4 Proj) { ///transform vertices to camera space and create a sprite HPS_DEPTH_VS_OUT OUT; float2 offset = texCoord.zw * baseRadius; OUT.r = abs(offset.x); float4 cPosition; cPosition = mul(worldView, position); OUT.center = cPosition; cPosition.xy += offset; OUT.cPosition = cPosition; OUT.cPosition.z += baseRadius; OUT.cPosition.z *= -1; ///projection OUT.hPosition = mul( Proj, cPosition ); ///calculate screen space coordinates float4 sPosition = OUT.hPosition / OUT.hPosition.w; OUT.screenCoord = (sPosition.xy + float2(1, 1)) / 2.0; OUT.screenCoord.y = 1.0 - OUT.screenCoord.y; OUT.texCoord = texCoord.xy; OUT.Color = Color; return OUT; } float4 HPS_Large_Depth_PS(HPS_DEPTH_VS_OUT IN, uniform sampler2D Texture : register(s0), uniform sampler2D depthTexture : register(s1), uniform sampler2D illumVolume : register(s2), uniform float farplane, uniform float nearplane ) : COLOR { float4 Color = 0; float4 impostor = tex2D(Texture, IN.texCoord); float f = 1.0 - impostor.g; float b = impostor.r; float alpha = 0; if(b == 0) discard; ////altering opacity according to scene depth float sceneDepth = tex2D(depthTexture, IN.screenCoord).r; if(sceneDepth == 0) sceneDepth = farplane; float size = 2.0 * IN.r; float frontDepth = IN.cPosition.z + size * (f - 0.5); float backDepth = IN.cPosition.z + size * (b - 0.5); float far = min(sceneDepth, backDepth); float near = max(frontDepth, nearplane); alpha = (far - near) / (backDepth - frontDepth); alpha = saturate(alpha) * impostor.a; ///final color Color = float4(1, 1, 1, alpha) * IN.Color; return Color; } ////////////// ///This shader is used when rendering the illumination volume of a HPS. Each color channel represents a layer of the volume. ///The vertex shader decides if a color channel (ie. a layer) should be written. ///////////// struct ILLUMVOLUME_VS_OUT { float4 hPosition : POSITION; float4 texCoord : TEXCOORD0; float4 color : COLOR0; }; ILLUMVOLUME_VS_OUT HPS_IllumVolume_VS(float4 position : POSITION, float4 texCoord : TEXCOORD0, float4 color : COLOR0, uniform float baseRadius, uniform float4x4 worldView, uniform float4x4 Proj) { ILLUMVOLUME_VS_OUT OUT; ///transform vertices to camera space and create a sprite texCoord.y = 1.0 - texCoord.y; float2 offset = texCoord.zw * baseRadius; float4 cPosition = mul(worldView, position); cPosition.xy += offset; ///project OUT.hPosition = mul( Proj, cPosition ); OUT.texCoord = texCoord; OUT.color = color.a; ////identify slices and set channels to zero if needed float z = OUT.hPosition.z / OUT.hPosition.w; float4 planes = float4(0.33, 0.5, 0.66, 1); if(z > planes.x) { OUT.color.r = 0; } if(z > planes.y) { OUT.color.g = 0; } if(z > planes.z) { OUT.color.b = 0; } return OUT; } float4 HPS_IllumVolume_PS(ILLUMVOLUME_VS_OUT IN , uniform sampler2D colorTexture : register(s0), uniform float density):COLOR //0.2 { return tex2D( colorTexture, IN.texCoord.xy).a * density * IN.color; } ////////////// ///This shader renders a HPS with depth calculation and with shading (light extintion). ///The pixel shader identifies the two layers of the illumination volume between wich the shaded point is, /// and interpolates the stored extintion values. ///////////// struct VS_OUT_DEPTH_ILLUM { float4 hPosition : POSITION; float4 cPosition : TEXCOORD1; float2 texCoord : TEXCOORD0; float r : TEXCOORD2; float4 center : TEXCOORD3; float4 Color : TEXCOORD4; float2 screenCoord : TEXCOORD5; float4 lightCoord : TEXCOORD6; }; VS_OUT_DEPTH_ILLUM HPS_Large_Depth_Illum_VS (float4 position : POSITION, float4 texCoord : TEXCOORD0, float4 Color: COLOR0, uniform float width, uniform float height, uniform float baseRadius, uniform float4x4 worldView, uniform float4x4 worldViewInv, uniform float4x4 lightViewProj, uniform float4x4 Proj) { ///transform vertices to camera space and create a sprite VS_OUT_DEPTH_ILLUM OUT; //texCoord.z = normalize(texCoord.z); //texCoord.w = normalize(texCoord.w); float2 offset = texCoord.zw * baseRadius; OUT.r = abs(offset.x); float4 cPosition; cPosition = mul(worldView, position); OUT.center = cPosition; cPosition.xy += offset; OUT.cPosition = cPosition; OUT.cPosition.z *= -1; //OUT.cPosition.z = OUT.cPosition.z - OUT.r; /// project OUT.hPosition = mul( Proj, cPosition ); /// calculate screen coordinates float4 sPosition = OUT.hPosition / OUT.hPosition.w; OUT.screenCoord = (sPosition.xy + float2(1.0, 1.0)) / float2(2.0, 2.0); float2 halfpixel = float2(0.5 / width, 0.5 / height); OUT.screenCoord += halfpixel; OUT.screenCoord.y = 1.0 - OUT.screenCoord.y; OUT.texCoord = texCoord.xy; OUT.Color = Color; ///calculate ligth space coordinates float4 wPosition = mul(worldViewInv, cPosition); OUT.lightCoord = mul(lightViewProj, wPosition); return OUT; } float4 HPS_Large_Depth_Illum_PS(VS_OUT_DEPTH_ILLUM IN, uniform sampler2D Texture : register(s0), uniform sampler2D depthTexture : register(s1), uniform sampler2D illumVolume : register(s2) ) : COLOR { float4 Color = 0; float4 impostor = tex2D(Texture, IN.texCoord); float f = 1.0 - impostor.g; float b = impostor.r; float alpha = 0; if(b == 0) discard; ////altering opacity according to scene depth float sceneDepth = tex2D(depthTexture, IN.screenCoord).r; if(sceneDepth == 0) { alpha = impostor.a; } else { float size = 2.0 * IN.r; float frontDepth = IN.cPosition.z + size * (f - 0.5); float backDepth = IN.cPosition.z + size * (b - 0.5); alpha = (sceneDepth - frontDepth) / (backDepth - frontDepth); alpha = saturate(alpha) * impostor.a; } ///identify light volume slices and interpolation float2 lightCoord; lightCoord = (IN.lightCoord.xy + float2(1.0, 1.0)) / 2.0; lightCoord.y = 1.0 - lightCoord.y; float z = IN.lightCoord.z / IN.lightCoord.w; float4 extintion = tex2D(illumVolume, lightCoord); float intensities[5]; intensities[0] = 1.0; intensities[1] = extintion.r; intensities[2] = extintion.g; intensities[3] = extintion.b; intensities[4] = extintion.a; float3 start; float3 end; float3 temp = 1.0; float t; float4 planes = float4(0.33, 0.5, 0.66, 1); if(z < planes.x) { start = intensities[0]; end = intensities[1]; t = z / planes.x; temp = lerp(start, end, t); } if(z > planes.x && z < planes.y) { start = intensities[1]; end = intensities[2]; t = (z - planes.x) / (planes.y - planes.x); temp = lerp(start, end, t); } if(z > planes.y && z < planes.z) { start = intensities[2]; end = intensities[3]; t = (z - planes.y) / (planes.z - planes.y); temp = lerp(start, end, t); } if(z > planes.z) { start = intensities[3]; end = intensities[4]; t = (z - planes.z) / (planes.a - planes.z); temp = lerp(start, end, t); } IN.Color.rgb *= temp; ///final color Color = float4(1, 1, 1, alpha) * IN.Color; return Color; }