struct Shaded_OUT { float4 vPos : POSITION; float4 wNormal : TEXCOORD0; float4 wPos : TEXCOORD1; }; ///////// /// Photon Map shaders ///////// float readDistanceCubeMap(samplerCUBE dcm, float3 coord) { float dist = texCUBE(dcm, float4(coord.xy, - coord.z, 0)).r; if(dist == 0) dist = 1000; ///sky return dist; } #define SECANT_ITERATIONCOUNT 2 ///Localization with secant iteration float3 Hit( float3 x, float3 R, samplerCUBE mp ) { float rl = readDistanceCubeMap( mp, R); // |r| float ppp = length( x ) / readDistanceCubeMap( mp, x); // |p|/|p’| float dun = 0, pun = ppp, dov = 0, pov = 0; float dl = rl * ( 1 - ppp ); // eq. 2 float3 l = x + R * dl; // ray equation // iteration for( int i = 0; i < SECANT_ITERATIONCOUNT; i++ ) { float llp = length( l ) / readDistanceCubeMap( mp, l); // |l|/|l’| if ( llp < 0.999f ) // undershooting { dun = dl; pun = llp; // last undershooting dl += ( dov == 0 ) ? rl * ( 1 - llp ) : // eq. 2 ( dl - dov ) * ( 1 - llp ) / ( llp - pov ); // eq. 3 } else if ( llp > 1.001f ) // overshooting { dov = dl; pov = llp; // last overshooting dl += ( dl -dun ) * ( 1 - llp ) / ( llp - pun );// eq. 3 } l = x + R * dl; // ray equation } return l; // computed hit point } //Hit the environment sampled by DistanceMap (single refraction) float4 PhotonMapHitEnvPS( Shaded_OUT IN, uniform float3 lastCenter, uniform float3 cameraPos, uniform float refIndex, uniform samplerCUBE DistanceMap : register(s0)):COLOR0 { float4 Color = float4(1,1,1,1); float3 wNormal = normalize(IN.wNormal); float3 dir; float3 cubeMapPos = IN.wPos.xyz - lastCenter; float3 V = normalize(IN.wPos.xyz - cameraPos); float3 R = refract(V, wNormal, refIndex); dir = R; dir = Hit(cubeMapPos, R, DistanceMap); Color = float4(dir, 1); if(dot(V, wNormal)>0) { Color = float4(1,0,0,0); } return Color; } ////// /// Caustic CubeMap shaders ////// ///point sprite caustic spots struct CauCube_PointSprite_VS_OUT { float4 hPosition : POSITION; float4 texCoord : TEXCOORD0; float4 color : COLOR0; float2 r : TEXCOORD1; float2 center : TEXCOORD2; float4 position : TEXCOORD3; float pSize : PSIZE; float dist : TEXCOORD4; }; CauCube_PointSprite_VS_OUT CauCube_PointSprite_VS( float4 position : POSITION, float4 texCoord : TEXCOORD0, float4 color : COLOR0, uniform float4x4 WorldView, uniform float4x4 Proj, uniform float CauSpriteSize, uniform sampler2D PhotonHitMap : register(s0)) { CauCube_PointSprite_VS_OUT OUT; float radius = CauSpriteSize; OUT.pSize = radius; float4 cPosition; float4 pos = tex2Dlod(PhotonHitMap, float4(position.x, 1.0 - position.y,0,0)).rgba; if(pos.a == 0)//no photon hit { OUT.center = 1000.0f; OUT.position = OUT.hPosition = -1000.0f; //transform out of view } else { float4 wPosition = float4(normalize(pos.xyz),1); cPosition = mul(WorldView, wPosition); OUT.center = cPosition.xy; OUT.position = cPosition; OUT.hPosition = mul(Proj, cPosition); } OUT.r.x = radius; OUT.r.y = radius; OUT.texCoord = texCoord; OUT.color = float4(pos); OUT.dist = length(pos.xyz); return OUT; } float4 CauCube_PointSprite_PS(CauCube_PointSprite_VS_OUT IN, uniform float4 CausticColor, uniform sampler2D intensityTex : register(s1) ):COLOR { IN.color = CausticColor; float intens = tex2D(intensityTex, IN.texCoord).r; IN.color.a *= intens; return IN.color; } //transformed caustic caster struct CauCube_Triangles_VS_OUT { float4 hPosition : POSITION; float4 color : COLOR0; }; CauCube_Triangles_VS_OUT CauCube_Triangles_VS( float4 position : POSITION, float4 texCoord : TEXCOORD0, float4 color : COLOR0, uniform float WorldSize, uniform float notUseIntensity, uniform float4x4 WorldView, uniform float4x4 Proj, uniform float PhotonMapResolution, uniform sampler2D PhotonHitMap : register(s0)) { CauCube_Triangles_VS_OUT OUT; float4 cPosition; float pixel = 1.0 / PhotonMapResolution; float2 uv = float2(position.x, 1.0 - position.y); uv += float2(pixel / 2.0,pixel / 2.0); float4 pos = tex2Dlod(PhotonHitMap, float4(uv,0,0)).rgba; if(pos.a == 0)//no photon hit { OUT.color = float4(0,0,0,0); OUT.hPosition = float4(1000000, 1000000, 1000000, 1); } else { float4 wPosition = float4(normalize(pos.xyz),1); cPosition = mul(WorldView, wPosition); OUT.hPosition = mul(Proj, cPosition); float intensity = 0.25; //read four neighbours float sumdist = 0; float dist; float valids = 0; float4 pos1 = tex2Dlod(PhotonHitMap, float4(uv + float2(pixel, pixel),0,0)); if(pos1.a != 0) { dist = length(pos1.xyz - pos.xyz); sumdist += dist; valids++; } float4 pos2 = tex2Dlod(PhotonHitMap, float4(uv + float2(-pixel, pixel),0,0)); if(pos2.a != 0) { dist = length(pos2.xyz - pos.xyz); sumdist += dist; valids++; } float4 pos3 = tex2Dlod(PhotonHitMap, float4(uv + float2(pixel, -pixel),0,0)); if(pos3.a != 0) { dist = length(pos3.xyz - pos.xyz); sumdist += dist; valids++; } float4 pos4 = tex2Dlod(PhotonHitMap, float4(uv + float2(-pixel, -pixel),0,0)); if(pos4.a != 0) { dist = length(pos4.xyz - pos.xyz); sumdist += dist; valids++; } float avrdist = sumdist / valids; if(valids == 0) avrdist = WorldSize / 1000.0; intensity = WorldSize / (avrdist * avrdist * 3.14); //intensity = 0.8; OUT.color = intensity; if(notUseIntensity) OUT.color = float4(1,1,1,1); } return OUT; } float4 CauCube_Triangles_PS(CauCube_Triangles_VS_OUT IN, uniform float4 CausticColor ):COLOR { return IN.color * CausticColor; } /////// /// Caustic gather shaders ////// float4 GatherCaustic_Cube_PS(Shaded_OUT IN, uniform samplerCUBE CauCubeMap : register(s0), uniform samplerCUBE DistanceCubeMap : register(s1), uniform float3 cubeMapCameraPosition, uniform float attenuation):COLOR { float4 Color = float4(1,1,1,1); float3 dir = IN.wPos - cubeMapCameraPosition; float4 caustic = texCUBE(CauCubeMap, float3(dir.xy, -dir.z) ); float mydist = length(dir); float dist = readDistanceCubeMap(DistanceCubeMap, dir); float EPSILON = 1; //if(mydist > dist + EPSILON) caustic = 0; caustic.rgb *= max(attenuation - mydist, 0.0) / attenuation; Color = caustic; Color.a = 1; return Color; }