float4 readCubeMap(samplerCUBE cm, float3 coord) { float4 color = texCUBElod( cm, float4(coord.xy, - coord.z,0) ); return color; } float readDistanceCubeMap(samplerCUBE dcm, float3 coord) { float dist = texCUBElod(dcm, float4(coord.xy, - coord.z,0)).a; return dist; } #define MAX_LIN_ITERATIONCOUNT 2 //80 #define MIN_LIN_ITERATIONCOUNT 1 //60 #define SECANT_ITERATIONCOUNT 1 #define MAX_RAY_DEPTH 2 void linearSearch( float3 x, float3 R, float3 N, samplerCUBE mp, out float3 p, out float dl, out float dp, out float llp, out float ppp) { float3 Ra = abs(R), xa = abs(x); float xm = max(max(xa.x,xa.y),xa.z); float Rm = max(max(Ra.x,Ra.y),Ra.z); float a = xm / Rm; int shootL = 0, shootP = 0; bool found = false; float dt = length(x / xm - R / Rm) * MAX_LIN_ITERATIONCOUNT; dt = max(dt, MIN_LIN_ITERATIONCOUNT); dt = 1.0 / dt; float t = 0.01;//dt; float pa; //Linear iteration while(t <= 1.0 && !found) { dp = a * t / (1 - t); p = x + R * dp; pa = readDistanceCubeMap(mp, p); if(pa > 0) { ppp = length(p) / pa; if(ppp < 1) shootP = -1; else shootP = 1; if(shootL * shootP == -1) found = true; else { shootL = shootP; dl = dp; llp = ppp; } } else shootL = 0; t += dt; } if(!found) p = float3(0,0,0); } void secantSearch(float3 x, float3 R, samplerCUBE mp, float dl, float dp, float llp, float ppp, out float3 p) { for(int i= 0; i < SECANT_ITERATIONCOUNT; i++) { float dnew; dnew = dl + (dp - dl) * (1 - llp) / (ppp - llp); p = x + R * dnew; half pppnew = length(p) / readDistanceCubeMap(mp, p); if(pppnew < 1) { llp = pppnew; dl = dnew; } else { ppp = pppnew; dp = dnew; } } } /* float3 Hit(float3 x, float3 R, float3 N, samplerCUBE mp1, samplerCUBE mp3Color, samplerCUBE mp3Dist, out float4 Il, out float3 Nl) { float dl1 = 0, dp1, llp1, ppp1; float3 p1; linearSearch(x, R, N, mp1, p1, dl1, dp1, llp1, ppp1); bool valid1 = dot(p1,p1) != 0; float dl, dp, llp, ppp; float3 p; if(!valid1) { linearSearch(x, R, N, mp3Dist, p, dl, dp, llp, ppp); Il.a = 1; secantSearch(x, R, mp3Dist, dl, dp, llp, ppp, p); Il.rgb = Nl.rgb = readCubeMap(mp3Color, p).rgb; } else { secantSearch(x, R, mp1, dl1, dp1, llp1, ppp1, p1); Il.rgb = Nl.rgb = readCubeMap(mp1, p1).rgb; p = p1; Il.a = 0; } return p; }*/ 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 } struct Shaded_OUT { float4 vPos : POSITION; float4 wNormal : TEXCOORD0; float4 wPos : TEXCOORD1; }; float4 MultipleRefractionPS(Shaded_OUT IN, uniform samplerCUBE CubeMap : register(s0), uniform samplerCUBE DistanceMap : register(s1), uniform samplerCUBE NormDistMap1 : register(s2), uniform float3 cameraPos, uniform float3 lastCenter, uniform float sFresnel, uniform float refIndex ) : COLOR0 { float4 I = float4(0,0,0,0); float3 N = normalize(IN.wNormal.xyz); float3 x = IN.wPos.xyz - lastCenter; float3 V = (IN.wPos.xyz - cameraPos); V = normalize(V); float F = sFresnel + pow(1 - dot(N, -V), 5) * (1 - sFresnel); float3 l; float ri = refIndex; float3 R; if(dot(V,N) > 0) { ri = 1.0 / refIndex; N = -N; } float4 Irefr = 0; R = refract( V, N, ri); if(dot(R,R) != 0) { R = refract( V, N, ri); l = Hit(x, R, DistanceMap); x = l; N = readCubeMap(NormDistMap1, l).rgb; V = R; if(dot(V,N) > 0) { ri = 1.0 / refIndex; N = -N; } R = refract( V, N, ri); if(dot(R,R) != 0) { l = Hit(x, R, DistanceMap); Irefr = readCubeMap(CubeMap, l); } } N = normalize(IN.wNormal.xyz); V = normalize(IN.wPos.xyz - cameraPos); x = IN.wPos.xyz - lastCenter; R = reflect( V, N); l = Hit(x, R, DistanceMap); float4 Irefl = readCubeMap(CubeMap, l); I = F * Irefl + (1 - F) * Irefr; return I; } float4 MultipleRefractionPhotonMap_PS(Shaded_OUT IN, uniform samplerCUBE DistanceMap : register(s0), uniform samplerCUBE NormDistMap1 : register(s1), uniform float3 cameraPos, uniform float3 lastCenter, uniform float refIndex) : COLOR0 { float4 I = float4(0,0,0,0); float3 N = normalize(IN.wNormal.xyz); float3 x = IN.wPos.xyz - lastCenter; float3 V = (IN.wPos.xyz - cameraPos); V = normalize(V); float3 l = 0; float ri = refIndex; float3 R; if(dot(V,N) > 0) { ri = 1.0 / refIndex; N = -N; } float4 Irefr = 0; R = refract( V, N, ri); if(dot(R,R) != 0) { R = refract( V, N, ri); l = Hit(x, R, DistanceMap); x = l; N = readCubeMap(NormDistMap1, l).rgb; V = R; if(dot(V,N) > 0) { ri = 1.0 / refIndex; N = -N; } R = refract( V, N, ri); if(dot(R,R) != 0) { l = Hit(x, R, DistanceMap); } } return float4(l,1); }