float3 F0; 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 20 #define MIN_LIN_ITERATIONCOUNT 6 #define SECANT_ITERATIONCOUNT 1 float Hit(float3 x, float3 R, samplerCUBE mp, out float3 newDir) { R = normalize(R); float3 Ra = abs(R); float3 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; float dt = length(x / xm - R / Rm) * MAX_LIN_ITERATIONCOUNT; dt = max(dt, MIN_LIN_ITERATIONCOUNT); dt = 1.0 / dt; bool overshoot = false, undershoot = false; float dp, dl = 0, ppp, llp; float lR = readDistanceCubeMap(mp, R); //float3 p = R; float3 p = 0; //linear iteration float t; float dist = 0; /* t = 0.9999999999999; dp = a * t / (1 - t); p = x + R * dp; dist = readDistanceCubeMap(mp, p); ppp = length(p) / dist; */ t = 0.01; while(t <= 1.0 && !overshoot) { dp = a * t / (1 - t); p = x + R * dp; float dist = readDistanceCubeMap(mp, p); if(dist > 0) { bool us = false; ppp = length(p) / dist; if(ppp < 1) us = true; us = !us; if(us) { dl = dp; llp = ppp; undershoot = true; } else { if (undershoot) overshoot = true; } } else undershoot = false; t += dt; } //if(t >= 1.0 && undershoot && dist) // overshoot = true; if(overshoot) { float dnew; for(int i = 0; i < SECANT_ITERATIONCOUNT; i++ ) { 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; } } } else p = float3(0,0,0); newDir = p; return dp; } float HitOld( float3 x, float3 R, samplerCUBE mp, out float3 newDir ) { //return R + 0.00000000001 * x; 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 } newDir = l; // computed hit point return dl; } struct VertOut { float3 wPos : TEXCOORD1; float3 cPos : TEXCOORD3; float2 texCoord : TEXCOORD0; float3 mNormal : TEXCOORD2; float4 hPos : POSITION; }; VertOut DefaultVS(float4 position : POSITION, float2 texCoord : TEXCOORD0, float3 normal : NORMAL, uniform float4x4 worldViewProj, uniform float4x4 world, uniform float4x4 worldview, uniform float4x4 worldI ) { VertOut OUT; OUT.hPos = mul(worldViewProj, position); OUT.wPos = mul(world, position).xyz; OUT.cPos = mul(worldview, position).xyz; OUT.mNormal = mul(normal, worldI); //OUT.mNormal = normal; OUT.texCoord = texCoord; return OUT; } ////////////// //Metal ////////////// float4 Metal1BouncePS( VertOut IN, uniform float3 cameraPos, uniform samplerCUBE CubeMap : register(s0), uniform samplerCUBE DistanceMap : register(s1), uniform float3 lastCenter):COLOR0 { float4 Color = float4(1,1,1,1); IN.mNormal = normalize(IN.mNormal); float3 newTexCoord; float3 mPos = IN.wPos - lastCenter; float3 V = (IN.wPos - cameraPos); float cameraDistace = length(V); V = normalize(V); float3 R = normalize(reflect( V, IN.mNormal)); newTexCoord = R; HitOld(mPos, R, DistanceMap, newTexCoord); Color = readCubeMap(CubeMap, newTexCoord ); float ctheta_in = dot(IN.mNormal,R); float ctheta_out = dot(IN.mNormal,-V); float3 F = 0; // F,P,G számítása if ( ctheta_in > 0 && ctheta_out > 0 ) { float3 H = normalize(R - V); // felezővektor float cbeta = dot(H,R); F = F0 + (1-F0)*pow(1-cbeta,5); } Color = Color * float4(F,1); return Color; } void MetalMultipleBouncePS( VertOut IN, uniform float3 cameraPos, uniform samplerCUBE CubeMap : register(s0), uniform samplerCUBE DistanceMap : register(s1), uniform samplerCUBE NormDistMap1 : register(s2), uniform samplerCUBE NormDistMap2 : register(s3), uniform float3 lastCenter, uniform float SingleBounce, out float4 Color :COLOR0) { //if(SingleBounce == 1) // Color = Metal1BouncePS(IN,cameraPos,CubeMap,DistanceMap,lastCenter); //else //{ Color = float4(1,1,1,1); IN.mNormal = normalize(IN.mNormal); float3 newTexCoord; float3 mPos = IN.wPos - lastCenter; float3 V = (IN.wPos - cameraPos); float cameraDistace = length(V); V = normalize(V); float3 R = normalize(reflect( V, IN.mNormal)); //float3 R = normalize(refract( V, IN.mNormal, 0.98)); newTexCoord = R; //Color = readCubeMap(NormDistMap2, mPos ); //return; float3 newDir1; float d1 = Hit(mPos, R, NormDistMap1, newDir1); float3 normal1 = readCubeMap(NormDistMap1, newDir1).rgb; bool valid1 = /*dot(normal1, R) < 0 &&*/ dot(newDir1,newDir1) != 0; if(valid1) newDir1 = 0; float3 newDir2; float d2 = Hit(mPos, R, NormDistMap2, newDir2); float3 normal2 = readCubeMap(NormDistMap2, newDir2).rgb; bool valid2 = /*dot(normal2, R) < 0 &&*/ dot(newDir2,newDir2) != 0; if(valid2) newDir2 = 0; if( !valid1 && !valid2) { // Hit(mPos, R, DistanceMap, newTexCoord); // Color = readCubeMap(CubeMap, newTexCoord ); //Color = 1; } else { float d; float3 newN; d = d2; newN = normal2; Color = float4(0,0,1,1); if( !valid2 || (valid1 && d1 < d2) ) { d = d1; newN = normal1; Color = float4(0,1,0,1); } float3 newV = R; float3 newX = mPos + R * d; float3 newR = normalize(reflect( newV, newN)); // float3 newR = normalize(refract( newV, newN, 0.98)); Hit(newX, newR, DistanceMap, newTexCoord); Color = readCubeMap(CubeMap, newTexCoord ); //Color = float4(newR,1); //Color = float4(1,0,0,1); } /* return; float ctheta_in = dot(IN.mNormal,R); float ctheta_out = dot(IN.mNormal,-V); float3 F = 0; // F,P,G számítása if ( ctheta_in > 0 && ctheta_out > 0 ) { float3 H = normalize(R - V); // felezővektor float cbeta = dot(H,R); F = F0 + (1-F0)*pow(1-cbeta,5); } Color = Color * float4(F,1); */ //} } float4 NormalDistancePS( VertOut IN, uniform float refIndex):COLOR { float4 Color = float4(0, 0, 0, 0); //return Color; Color = float4(normalize(IN.mNormal)/* * refIndex*/, length(IN.cPos)); return Color; } float4 DistanceMinMaxPS( VertOut IN, uniform float refIndex):COLOR { float4 Color = float4(0, 0, 0, 0); Color = float4(length(IN.cPos), 0,0,length(IN.cPos)); return Color; }