diff --git a/src/shaders/fragment.frag b/src/shaders/fragment.frag index 9a348d5..320c15f 100644 --- a/src/shaders/fragment.frag +++ b/src/shaders/fragment.frag @@ -107,34 +107,106 @@ vec2 opU(vec2 d1, vec2 d2) { return (d1.x < d2.x) ? d1 : d2; } -vec2 mapScene(in vec3 p) { +#define PI 3.14159265 +#define TAU 6.2831853 +#define HEX_SIZE 1.0 +#define PYLON_HEIGHT 4.0 - float res = p.y; - float mat = 0.; - - float hexRadius = 0.83; - vec3 hexpos = vec3(p.x, p.y - 2.5, p.z); - HexData hex = hexTile(hexpos, 1.1); - - float distFromCenter = hexDistance(hex.axial); - int fftIndex = int(cl(distFromCenter + 1.0, 0.0, 511.0)); - float fftVal = fft_output[fftIndex]; - float noise = mix(noise(hex.axial+1., 0.1), noise(hex.axial+1., 0.2), sin(syncs[0] * 4.)); - float hexHeight = clamp(1.0 + fftVal * 5.0 + noise, 0., 15.);; - - // Rotate individual hex tiles if needed - vec3 r = hex.local; - // r.yz *= rot2D(PI * 0.5); - r.xz *= rot2D(0.5); - - //float d1 = hexPylon(vec3(r.x, (r.y + hexHeight / 2), r.z), vec2(hexRadius, hexHeight / 2)); - float d1 = hexPylon(vec3(r.x, r.y, r.z), vec2(hexRadius, hexHeight)); - - res = (d1 < res) ? d1 : res; - - return vec2(res, mat); +// Rotate 2D vector +vec2 rotate(vec2 p, float a) { + float s = sin(a), c = cos(a); + return vec2(c*p.x - s*p.y, s*p.x + c*p.y); } +// Hexagonal tiling +vec2 hex(vec2 p) { + vec2 q = vec2( + p.x * 2.0 / 3.0, + (-p.x + sqrt(3.0) * p.y) / 3.0 + ); + return q; +} + +// Signed distance function for pylon +float pylon(vec3 p) { + float radius = 0.5; + float d = length(p.xz) - radius; + d = max(d, -p.y); + d = max(d, p.y - PYLON_HEIGHT); + return d; +} + +// Scene mapping with occlusion-aware SDF blending +vec2 mapScene(vec3 p) { + + //vec2 h = hex(p.xz / HEX_SIZE); + //vec2 id = floor(h); + //vec2 f = fract(h); + float dist = 20.; + int repeat = 0; + if((length(p.xz)) < 2*dist){ + repeat = 2; + } + if((length(p.xz)) < 1.5*dist){ + repeat = 3; + } + if((length(p.xz)) < dist){ + repeat = 5; + } + + //int repeat = 2; + // mitigate neighbor occlusion with anti-bleed blending + float minDist = 1e9; + for (int dx = -repeat; dx <= repeat; ++dx) { + for (int dy = -repeat; dy <= repeat; ++dy) { + vec2 offset = vec2(dx, dy); + vec3 hexpos = vec3(p.x-dx, p.y - 2.5, p.z-dy); + HexData hex = hexTile(hexpos, 1.1); + float distFromCenter = hexDistance(hex.axial); + int fftIndex = int(cl(distFromCenter + 1.0, 0.0, 511.0)); + float fftVal = fft_output[fftIndex]; + float noise = mix(noise(hex.axial+1., 0.1), noise(hex.axial+1., 0.2), sin(syncs[0] * 4.)); + float hexHeight = clamp(1.0 + fftVal * 5.0 + noise, 0., 15.); + vec3 r = vec3(hex.local.x + offset.x,hex.local.y,hex.local.z+offset.y); + // r.yz *= rot2D(PI * 0.5); + r.xz *= rot2D(0.5); + vec3 cellPos = r; + float d = fHexagonCircumcircle(cellPos, vec2(0.85, hexHeight)); + minDist = min(minDist, d); + } + } + return vec2(minDist,0.); +} + + +//vec2 mapScene(in vec3 p) { +// +// float res = p.y; +// float mat = 0.; +// +// float hexRadius = 0.83; +// vec3 hexpos = vec3(p.x, p.y - 2.5, p.z); +// HexData hex = hexTile(hexpos, 1.1); +// +// float distFromCenter = hexDistance(hex.axial); +// int fftIndex = int(cl(distFromCenter + 1.0, 0.0, 511.0)); +// float fftVal = fft_output[fftIndex]; +// float noise = mix(noise(hex.axial+1., 0.1), noise(hex.axial+1., 0.2), sin(syncs[0] * 4.)); +// float hexHeight = clamp(1.0 + fftVal * 5.0 + noise, 0., 15.);; +// +// // Rotate individual hex tiles if needed +// vec3 r = hex.local; +// // r.yz *= rot2D(PI * 0.5); +// r.xz *= rot2D(0.5); +// +// //float d1 = hexPylon(vec3(r.x, (r.y + hexHeight / 2), r.z), vec2(hexRadius, hexHeight / 2)); +// float d1 = hexPylon(vec3(r.x, r.y, r.z), vec2(hexRadius, hexHeight)); +// +// res = (d1 < res) ? d1 : res; +// +// return vec2(res, mat); +//} + //////////////// // RAYCAST // //////////////// @@ -142,29 +214,72 @@ vec2 mapScene(in vec3 p) { vec3 castRay(vec3 ro, vec3 rd, inout vec3 pos) { float mat = 0.; float hit = 0.; - float t = 0.; + vec3 d; + float t = 0.,ad,tmax=200.; // total distance travelled + const float tolerance = 0.0001; + const float Z_REPEAT_DIST = 1.5; vec2 res; // Raymarching - for(int i = 0; i < 40; i++) { + for (int i = 0; i < 50; i++) { pos = ro + rd * t; - res = mapScene(pos); // Get distance to objects, x = dist, y = material + res = mapScene(pos); // Get distance to objects + ad = abs(res.x); mat = res.y; - t += res.x; // "march" the ray - - // if(abs(t) < tolerance * (t * 0.0125 + 1.0)) { - if(abs(res.x) < 0.0001) { - hit = 1.; + if (t > tmax) break; + if (ad < tolerance*(t*0.00125 + 1.0)) { + hit = 1.0; break; } - if(t > 200) - break; - + t += res.x; // "march" the ray } +// t -= Z_REPEAT_DIST/2.0; +// +// for( int i=0; i<20; i++ ) +// { +// vec3 pos2 = ro + rd * t; +// res = mapScene(pos2); // get distance to objects +// ad = abs(res.x); +// mat = res.y; +// if (ad < (tolerance)) +// { +// hit = 1.0; +// pos = pos2; +// break; +// } +// if (t > tmax) break; +// t += min(d.x, Z_REPEAT_DIST/5.0); // "march" the ray +// } return vec3(t, mat, hit); } +//vec3 castRay(vec3 ro, vec3 rd, inout vec3 pos) { +// float mat = 0.; +// float hit = 0.; +// float t = 0.; +// vec2 res; +// +// // Raymarching +// for(int i = 0; i < 50; i++) { +// pos = ro + rd * t; +// res = mapScene(pos); // Get distance to objects, x = dist, y = material +// mat = res.y; +// t += res.x; // "march" the ray +// +// // if(abs(t) < tolerance * (t * 0.0125 + 1.0)) { +// if(abs(res.x) < 0.001) { +// hit = 1.; +// break; +// } +// if(t > 300) +// break; +// +// } +// +// return vec3(t, mat, hit); +//} + //////////////// // SHADING // ////////////////