#define CUBEMAP_SIZE 128 #define REDUCED_CUBEMAP_SIZE 4 #define RATE 32 float4 readCubeMap(samplerCUBE cm, float3 coord) { float4 color = texCUBElod( cm, float4(coord.xy, -coord.z, 1) ); color.a = 1; return color; } float readDistanceCubeMap(samplerCUBE dcm, float3 coord) { float dist = texCUBElod(dcm, float4(coord.xy, - coord.z, 1)).r; if(dist == 0) dist = 1000000; ///sky return dist; } //////////////////////////// /// Reduce cube map shader /////////////////////////// struct MPos_OUT { float4 VPos : POSITION; float4 MPos : TEXCOORD0; }; float4 ReduceCubeMap_PS(MPos_OUT IN, uniform int nFace, uniform samplerCUBE EnvironmentMapSampler : register(s0) ) : COLOR { float4 color = 0; float3 dir; for (int i = 0; i < RATE; i++) for (int j = 0; j < RATE; j++) { float2 pos; pos.x = IN.MPos.x + (2*i + 1)/(float)CUBEMAP_SIZE; pos.y = IN.MPos.y - (2*j + 1)/(float)CUBEMAP_SIZE; // y=-u // "scrambling" if (nFace == 0) dir = float3(1, pos.y, -pos.x); if (nFace == 1) dir = float3(-1, pos.y, pos.x); if (nFace == 2) dir = float3(pos.x, 1, -pos.y); if (nFace == 3) dir = float3(pos.x, -1, pos.y); if (nFace == 4) dir = float3(pos.x, pos.y, 1); if (nFace == 5) dir = float3(-pos.x, pos.y,-1); color += texCUBE( EnvironmentMapSampler, dir); } return color / (RATE * RATE); } //////////////// /// Diffuse /////////////// /// Polygon to point form factor float4 Poly2Point_Contr(float3 L, float3 L1, float3 L2, float3 L3, float3 L4, float3 pos, float3 N, samplerCUBE cubemap) { float d; //d = texCUBE(cubemap, L).a; d = readDistanceCubeMap(cubemap, L1).r; L1 = d * normalize(L1); d = readDistanceCubeMap(cubemap, L2).r; L2 = d * normalize(L2); d = readDistanceCubeMap(cubemap, L3).r; L3 = d * normalize(L3); d = readDistanceCubeMap(cubemap, L4).r; L4 = d * normalize(L4); float3 r1 = normalize(L1 - pos); float3 r2 = normalize(L2 - pos); float3 r3 = normalize(L3 - pos); float3 r4 = normalize(L4 - pos); /* float tri1 = acos(dot(r1, r2)) * dot(cross(r1, r2), N); float tri2 = acos(dot(r2, r3)) * dot(cross(r2, r3), N); float tri3 = acos(dot(r3, r4)) * dot(cross(r3, r4), N); float tri4 = acos(dot(r4, r1)) * dot(cross(r4, r1), N); */ float3 crossP = cross(r1, r2); float r = length(crossP); float dd = dot(r1,r2); float tri1 = acos(dd) * dot(crossP/r, N); crossP = cross(r2, r3); r = length(crossP); dd = dot(r1,r2); float tri2 = acos(dd) * dot(crossP/r, N); crossP = cross(r3, r4); r = length(crossP); dd = dot(r1,r2); float tri3 = acos(dd) * dot(crossP/r, N); crossP = cross(r4, r1); r = length(crossP); dd = dot(r1,r2); float tri4= acos(dd) * dot(crossP/r, N); return max(tri1 + tri2 + tri3 + tri4, 0); //return tri1 + tri2 + tri3 + tri4; } struct Shaded_OUT { float4 vPos : POSITION; float4 wNormal : TEXCOORD0; float4 wPos : TEXCOORD1; }; float4 Diffuse_Poly2Point_PS( Shaded_OUT IN, uniform float3 lastCenter, uniform samplerCUBE SmallEnvMapSampler : register(s0), uniform samplerCUBE DistanceEnvMapSampler : register(s1) ) : COLOR0 { float M = REDUCED_CUBEMAP_SIZE; float3 N = IN.wNormal.xyz; N = normalize( N ); float3 pos = IN.wPos.xyz - lastCenter; float4 I = 0; float3 L1, L2, L3, L4, L; float4 Le; float width = 1.0 / M; float width2 = width * 2; float d; for (float x = 1; x < M; x++) for (float y = 1; y < M; y++) { float2 p, tpos; tpos.x = x * width; tpos.y = y * width; p = tpos.xy; p = 2.0 * p - 1.0; //-1..1 L1 = float3(p.x - width, p.y - width, 1); L2 = float3(p.x + width, p.y - width, 1); L3 = float3(p.x + width, p.y + width, 1); L4 = float3(p.x - width, p.y + width, 1); L = float3(p.x, p.y, 1); Le = float4(readCubeMap(SmallEnvMapSampler, L).rgb, 1); I += 0.5 * Le * Poly2Point_Contr( L, L1, L2, L3, L4, pos, N, DistanceEnvMapSampler); } for (float x = 1; x < M; x++) for (float y = 1; y < M; y++) { float2 p, tpos; tpos.x = x * width; // 0..1 tpos.y = y * width; // 0..1 p = tpos.xy; p = 2.0 * p - 1.0; //-1..1 L4 = float3(p.x - width, p.y - width, -1); L3 = float3(p.x + width, p.y - width, -1); L2 = float3(p.x + width, p.y + width, -1); L1 = float3(p.x - width, p.y + width, -1); L = float3(p.x, p.y, -1); Le = float4(readCubeMap(SmallEnvMapSampler, L).rgb, 1); I += 0.5 * Le * Poly2Point_Contr( L, L1, L2, L3, L4, pos, N, DistanceEnvMapSampler); } for (float x = 1; x < M; x++) for (float y = 1; y < M; y++) { float2 p, tpos; tpos.x = x * width; // 0..1 tpos.y = y * width; // 0..1 p = tpos.xy; p = 2.0 * p - 1.0; //-1..1 L4 = float3(p.x - width, 1, p.y - width); L3 = float3(p.x + width, 1, p.y - width); L2 = float3(p.x + width, 1, p.y + width); L1 = float3(p.x - width, 1, p.y + width); L = float3(p.x, 1, p.y); Le = float4(readCubeMap(SmallEnvMapSampler, L).rgb, 1); I += 0.5 * Le * Poly2Point_Contr( L, L1, L2, L3, L4, pos, N, DistanceEnvMapSampler); } for (float x = 1; x < M; x++) for (float y = 1; y < M; y++) { float2 p, tpos; tpos.x = x * width; // 0..1 tpos.y = y * width; // 0..1 p = tpos.xy; p = 2.0 * p - 1.0; //-1..1 L1 = float3(p.x - width, -1, p.y - width); L2 = float3(p.x + width, -1, p.y - width); L3 = float3(p.x + width, -1, p.y + width); L4 = float3(p.x - width, -1, p.y + width); L = float3(p.x, -1, p.y); Le = float4(readCubeMap(SmallEnvMapSampler, L).rgb, 1); I += 0.5 * Le * Poly2Point_Contr( L, L1, L2, L3, L4, pos, N, DistanceEnvMapSampler); } for (float x = 1; x < M; x++) for (float y = 1; y < M; y++) { float2 p, tpos; tpos.x = x * width; // 0..1 tpos.y = y * width; // 0..1 p = tpos.xy; p = 2.0 * p - 1.0; //-1..1 L1 = float3(1, p.x - width, p.y - width); L2 = float3(1, p.x + width, p.y - width); L3 = float3(1, p.x + width, p.y + width); L4 = float3(1, p.x - width, p.y + width); L = float3(1, p.x, p.y); Le = float4(readCubeMap(SmallEnvMapSampler, L).rgb, 1); I += 0.5 * Le * Poly2Point_Contr( L, L1, L2, L3, L4, pos, N, DistanceEnvMapSampler); } for (float x = 1; x < M; x++) for (float y = 1; y < M; y++) { float2 p, tpos; tpos.x = x * width; // 0..1 tpos.y = y * width; // 0..1 p = tpos.xy; p = 2.0 * p - 1.0; //-1..1 L4 = float3(-1, p.x - width, p.y - width); L3 = float3(-1, p.x + width, p.y - width); L2 = float3(-1, p.x + width, p.y + width); L1 = float3(-1, p.x - width, p.y + width); L = float3(-1, p.x, p.y); Le = float4(readCubeMap(SmallEnvMapSampler, L).rgb, 1); I += 0.5 * Le * Poly2Point_Contr( L, L1, L2, L3, L4, pos, N, DistanceEnvMapSampler); } float kd = 0.32; return kd * I; } /// Point to point form factor float4 Point2Point_Contr(float3 N, float3 Nl, float3 pos, float3 L, samplerCUBE cubemap, samplerCUBE distmap) { Nl = normalize(Nl); L = normalize(L); float4 Le = readCubeMap(cubemap, L); float d = readDistanceCubeMap(distmap, L); float3 Lpos = L * d; float3 Ldir = Lpos - pos; float dist = 4 * dot(Ldir, Ldir); Ldir = normalize(Ldir); return Le * (max(dot(N, Ldir),0) * dot(Nl, -1 * Ldir)) / dist; } float4 Diffuse_Point2Point_PS( Shaded_OUT IN, uniform float3 lastCenter, uniform samplerCUBE SmallEnvMapSampler : register(s0), uniform samplerCUBE DistanceEnvMapSampler : register(s1)) : COLOR { float M = REDUCED_CUBEMAP_SIZE; float3 N = IN.wNormal.xyz; N = normalize( N ); float3 pos = IN.wPos.xyz - lastCenter; float4 I = 0; float3 L; float4 Le; float width = 1.0 / M; float d; float kd = 1.0; for (float x = 0.5; x < M; x++) for (float y = 0.5; y < M; y++) { float2 p, tpos; tpos.x = x * width; tpos.y = y * width; p = tpos.xy; p = 2.0 * p - 1.0; //-1..1 I += Point2Point_Contr(N, float3(0,0,-1), pos, float3(p.x, p.y, 1), SmallEnvMapSampler, DistanceEnvMapSampler); I += Point2Point_Contr(N, float3(0,0,1), pos, float3(-p.x, p.y, -1), SmallEnvMapSampler, DistanceEnvMapSampler); I += Point2Point_Contr(N, float3(-1,0,0), pos, float3(1, p.y, -p.x), SmallEnvMapSampler, DistanceEnvMapSampler); I += Point2Point_Contr(N, float3(1,0,0), pos, float3(-1, p.y, p.x), SmallEnvMapSampler, DistanceEnvMapSampler); I += Point2Point_Contr(N, float3(0,-1,0), pos, float3(p.x, 1, -p.y), SmallEnvMapSampler, DistanceEnvMapSampler); I += Point2Point_Contr(N, float3(0,1,0), pos, float3(p.x, -1, p.y), SmallEnvMapSampler, DistanceEnvMapSampler); } return kd * I; } /// Disc to point form factor float4 Disc2Point_Contr(float3 L, float3 pos, float3 N, float3 V, samplerCUBE SmallEnvMapSampler, samplerCUBE DistanceEnvMapSampler) // Phong-Blinn // L: a hossza lényeges (az egységkocka faláig ér) { float mindist = 1.0; float kd = 0.3; // 0.3 float ks = 0; // 0.5 float shininess = 10; float l = length(L); L = normalize(L); //dw float dw = 4 / (REDUCED_CUBEMAP_SIZE*REDUCED_CUBEMAP_SIZE*l*l*l + 4/3.1416f); //Lin float4 Lin = readCubeMap(SmallEnvMapSampler, L); //r float doy = readDistanceCubeMap(DistanceEnvMapSampler, L); float dxy = length(L * doy - pos); dxy = max(mindist, dxy); //dws float dws = (doy*doy * dw) / (dxy*dxy*(1 - dw/3.1416f) + doy*doy*dw/3.1416f); // localization: //float dws = dw; //L = L * doy - pos; // L: x->y, az objektumtól induljon, ne a középpontból L = normalize(L); float3 H = normalize(L + V); // felezővektor float a = kd * max(dot(N,L),0) + ks * pow(max(dot(N,H),0), shininess); // diffuse + specular // 1.: eddigi //return Lin * a * dws; float ctheta_in = dot(N,L); float ctheta_out = dot(N,V); return Lin * a * dws; } float4 Diffuse_Disc2Point_PS(Shaded_OUT IN, uniform float3 lastCenter, uniform float3 cameraPos, uniform samplerCUBE SmallEnvMapSampler : register(s0), uniform samplerCUBE DistanceEnvMapSampler : register(s1) ) : COLOR0 { float M = REDUCED_CUBEMAP_SIZE; float3 N = IN.wNormal.xyz; N = normalize( N ); float3 V = normalize(IN.wPos.xyz - cameraPos); float3 pos = IN.wPos.xyz - lastCenter; float4 I = 0; float3 L; float4 Le; float width = 1.0 / M; float d; for (float x = 0.5; x < M; x++) for (float y = 0.5; y < M; y++) { float2 p, tpos; tpos.x = x * width; tpos.y = y * width; p = tpos.xy; p = 2.0 * p - 1.0; //-1..1 float3 L; L = float3(p.x, p.y, 1); I += Disc2Point_Contr( L, pos, N, V, SmallEnvMapSampler, DistanceEnvMapSampler); L = float3(p.x, p.y, -1); I += Disc2Point_Contr( L, pos, N, V, SmallEnvMapSampler, DistanceEnvMapSampler); L = float3(p.x, 1, p.y); I += Disc2Point_Contr( L, pos, N, V, SmallEnvMapSampler, DistanceEnvMapSampler); L = float3(p.x, -1, p.y); I += Disc2Point_Contr( L, pos, N, V, SmallEnvMapSampler, DistanceEnvMapSampler); L = float3(1, p.x, p.y); I += Disc2Point_Contr( L, pos, N, V, SmallEnvMapSampler, DistanceEnvMapSampler); L = float3(-1, p.x, p.y); I += Disc2Point_Contr( L, pos, N, V, SmallEnvMapSampler, DistanceEnvMapSampler); } float kd = 1.0; return kd * I; }