From e092075c8bb1ed09ee2ad790632ca3f5c08d06eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20J=C3=A4rvisalo?= Date: Mon, 28 Jul 2025 02:10:39 +0300 Subject: [PATCH] uudet hexat integroitu teemun shaderiin --- src/fft.cpp | 4 +- src/main.cpp | 67 ++++++----- src/shaders/fragment.frag | 243 ++++++++++++++++++++++++-------------- src/shaders/fragment.inl | 235 ++++++++++++++++++++---------------- 4 files changed, 331 insertions(+), 218 deletions(-) diff --git a/src/fft.cpp b/src/fft.cpp index fd85612..441604b 100644 --- a/src/fft.cpp +++ b/src/fft.cpp @@ -71,8 +71,8 @@ void compute_fft(float* time_data, float* freq_out) { for (int i = 0; i < FFT_SIZE / 2; ++i) { float mag = sqrtf(real[i] * real[i] + imag[i] * imag[i]) / FFT_SIZE; - //float db = 20.0f * log10f(mag + 1e-6f); // Decibels - //float normalized = (db + 60.0f) / 60.0f; // [0,1] + float db = 20.0f * log10f(mag + 1e-6f); // Decibels + float normalized = (db + 60.0f) / 60.0f; // [0,1] freq_out[i] = mag; } } diff --git a/src/main.cpp b/src/main.cpp index c3ef5a5..28ecfb5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -203,8 +203,13 @@ int __cdecl main(int argc, char* argv[]) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + const ULONGLONG targetIntervalMs = 1000 / 60; // For 60 FPS FFT updates + do { + static ULONGLONG lastFFTTime = 0; + ULONGLONG currentTime = GetTickCount64(); + direct_sound_buffer->GetCurrentPosition((DWORD*)&playCursor, NULL); #if !(DESPERATE) @@ -235,42 +240,44 @@ int __cdecl main(int argc, char* argv[]) #endif - /****************** - * FFT - *******************/ - LPVOID audio_ptr = NULL; - DWORD audio_size = 0; + if (currentTime - lastFFTTime >= targetIntervalMs) { + lastFFTTime = currentTime; + /****************** + * FFT + *******************/ + LPVOID audio_ptr = NULL; + DWORD audio_size = 0; - // Read audio - HRESULT hr = IDirectSoundBuffer_Lock(direct_sound_buffer, 0, FFT_SIZE * sizeof(SUsample), &audio_ptr, &audio_size, NULL, NULL, DSBLOCK_FROMWRITECURSOR); + // Read audio + HRESULT hr = IDirectSoundBuffer_Lock(direct_sound_buffer, 0, FFT_SIZE * sizeof(SUsample), &audio_ptr, &audio_size, NULL, NULL, DSBLOCK_FROMWRITECURSOR); - if (SUCCEEDED(hr) && audio_ptr) { - if (playCursor < ((SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT * SU_SAMPLE_SIZE) - (FFT_SIZE* SU_CHANNEL_COUNT * SU_SAMPLE_SIZE))) - { - SUsample* samples = (SUsample*)audio_ptr; - for (int i = 0; i < FFT_SIZE; ++i) { - fft_input[i] = (float)samples[i]; + if (SUCCEEDED(hr) && audio_ptr) { + if (playCursor < ((SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT * SU_SAMPLE_SIZE) - (FFT_SIZE * SU_CHANNEL_COUNT * SU_SAMPLE_SIZE))) + { + SUsample* samples = (SUsample*)audio_ptr; + for (int i = 0; i < FFT_SIZE; ++i) { + fft_input[i] = (float)samples[i]; + } } + + IDirectSoundBuffer_Unlock(direct_sound_buffer, audio_ptr, audio_size, NULL, 0); } - IDirectSoundBuffer_Unlock(direct_sound_buffer, audio_ptr, audio_size, NULL, 0); + // Calculate FFT + compute_fft(fft_input, fft_output); + + // Normalize output + for (int i = 0; i < (FFT_SIZE / 4); i++) + { + float gain = 50.0f; + float alpha = 0.10f; // "Hidastaa" FFT:n piikkejä + float threshhold = 0.05f; // Alin arvo mikä päästetään shaderille (vähentää "noisea") + float x_t = fft_output[i] * gain; + // Exponential smoothing kaava + // s(t) = alpha*x(t)+(1-alpha)*s(t-1) + fft_uniform[i] = (x_t < threshhold) ? 0.f : alpha * (x_t)+(1 - alpha) * fft_uniform[i]; + } } - - // Calculate FFT - compute_fft(fft_input, fft_output); - - // Normalize output - for (int i = 0; i < (FFT_SIZE / 4); i++) - { - float gain = 50.0f; - float alpha = 0.15f; // "Hidastaa" FFT:n piikkejä - float threshhold = 0.05f; // Alin arvo mikä päästetään shaderille (vähentää "noisea") - float x_t = fft_output[i] * gain; - // Exponential smoothing kaava - // s(t) = alpha*x(t)+(1-alpha)*s(t-1) - fft_uniform[i] = (x_t < threshhold) ? 0.f : alpha*(x_t) + (1-alpha)*fft_uniform[i]; - } - syncs[0] = (float)playCursor / (SU_SAMPLE_RATE * SU_CHANNEL_COUNT * SU_SAMPLE_SIZE); // Aika sekunteina. for (int i = 0; i < SU_NUMSYNCS; ++i) diff --git a/src/shaders/fragment.frag b/src/shaders/fragment.frag index 1c8c117..80d6046 100644 --- a/src/shaders/fragment.frag +++ b/src/shaders/fragment.frag @@ -35,34 +35,107 @@ float noise(in vec2 xy, in float seed) { return fract(tan(distance(xy * PHI, xy) * seed) * xy.x); } -float getScaledFFT(int index, float scale, float offset) { - // Clamp index to valid range - index = clamp(index, 0, 511); - - // Get raw FFT value - float raw = fft_output[index]; - - // Apply logarithmic scaling: log(1 + value * scale) + offset - return log(1.0 + raw * scale) + offset; -} - ///////////////// // GEOMETRY // ///////////////// -// Hexagonal prism, circumcircle variant float fHexagonCircumcircle(vec3 p, vec2 h) { vec3 q = abs(p); return max(q.y - h.y, max(q.x * sqrt(3.) * 0.5 + q.z * 0.5, q.z) - h.x); - //this is mathematically equivalent to this line, but less efficient: - //return max(q.y - h.y, max(dot(vec2(cos(PI/3), sin(PI/3)), q.zx), q.z) - h.x); } -float sdHex(vec3 pos, float i, float angle) { - float d1 = fHexagonCircumcircle(pos, vec2(0.86, i)); - return d1; +float hexPylon(vec3 p, vec2 h) {//float r, float ht){ + + //vec3 p = vec3(p.x, p.z, p2.y); + vec3 b = vec3(h.x, h.y, h.x); + + // Hexagon. + p.xz = abs(p.xz); + p.xz = vec2(p.x*.866025 + p.z*.5, p.z); + // The ".015" is a subtle rounding factor. Zero gives sharp edges, + // and larger numbers give a more rounded look. + return length(max(abs(p) - b + .015, 0.)) - .015; } +#define zclamp(a) max(a,0.0) //Clamp negative values at zero +float DF_RoundedHex( vec3 p, vec2 h) //float width, float height) +{ + float width = h.x; + float height = h.y; + //Modified version (smooth edges) of the exagon prism found here: + //https://iquilezles.org/articles/distfunctions + float smoothRadius = 0.05; + width -= smoothRadius*2.0; + + //Hexagon prism constructed using X,Y,Z symmetry. + //Only quadrant 1 needs to be solved, but the joining diagonal to quadrant IV is also + //required for distance blending (see db). + p = abs(p); + + //Hexagonal edge distances : + //Note : [.8666,0.5] = [sin(PI/3,cos(PI/3)] -> Hexagon edges rotation coeff (60 degrees). + float da = (p.x*0.866025+p.z*0.5)-width; //quadrant I diagonal edge distance + float db = (p.x*0.866025-p.z*0.5)-width; //quadrant IV diagonal edge distance (needed for blending) + float dc = p.z-width; //upper distance + + vec3 d = zclamp(vec3(da,db,dc)); + //Note: this is not an euclidian length, therefore this operation slightly distorts our distance field. + //Yet, it is harmless to convergence, and does the smoothing job quite well. + float dw = length(d)-smoothRadius; //hexagonal part smoothness (blending at 60 deg) + float dh = p.y-height; + + //Now that we have xz distance(dw) and y distance (dh), we can compute the distance + //for the given isovalue (the smoothing radius). + //Note : internal distance (maxX,maxY,maxZ) is also used to genereate internal signed dist, + // helping convergence when overstepping (very frequent with domain repetition). + float externalDistance = length(zclamp(vec2(dh,dw)))-smoothRadius; //Smoothed, unsigned + float internalDistance = max(max(da,dc),dh); //Sharp, signed. + return min(externalDistance,internalDistance); +} + +// Return local coordinates inside hex AND axial ID +struct HexData { + vec3 local; // Local position inside hex + vec2 axial; // Axial ID (q, r) +}; + +HexData hexTile(vec3 p, float radius) { + float q = (sqrt(3.0)/3.0 * p.x - 1.0/3.0 * p.z) / radius; + float r = (2.0/3.0 * p.z) / radius; + + float rq = round(q); + float rr = round(r); + float rs = round(-q - r); + + float dq = abs(rq - q); + float dr = abs(rr - r); + float ds = abs(rs + q + r); + + if (dq > dr && dq > ds) rq = -rr - rs; + else if (dr > ds) rr = -rq - rs; + + float hx = radius * sqrt(3.0) * (rq + rr * 0.5); + float hz = radius * 1.5 * rr; + + HexData outData; + outData.local = p - vec3(hx, 0.0, hz); + outData.axial = vec2(rq, rr); // Hex ID + return outData; +} + +struct HexData { + vec3 local; + vec2 axial; +}; + +float hexDistance(vec2 axial) { + float q = axial.x; + float r = axial.y; + float s = -q - r; + return max(abs(q), max(abs(r), abs(s))); +} + + float sdSphere(vec3 p, float r){ return length(p) -r; } @@ -86,69 +159,27 @@ vec2 mapScene(in vec3 p) { float mat = 1.; float d = 1e9; float a = 0.; + float hexRadius = 0.83; + + vec3 hexpos = vec3(p.x, p.y - 2.5, p.z); - vec2 rippleCenter = vec2(7.,7.); - float rippleSpeed = 4.0; - float rippleFreq = 1.0; - float rippleDecay = 0.25; + HexData hex = hexTile(hexpos, 1.0); - // Hexagonal grid - float hexGap = 0.2; - /* - for(float j = 0.; j < 16.; j++) { - vec3 po = p-vec3(-2.0,-5., 0.0); - po += vec3((1.6 + hexGap) * 8, -5., -(1.88 + hexGap) * 10); - po += vec3(0, 0., (1.88 + hexGap) * j); + // Use axial coordinates as a stable hex ID + float distFromCenter = hexDistance(hex.axial); + int fftIndex = int(clamp(distFromCenter +1.0, 0.0, 511.0)); // tweak 15.0 to taste - for(float i = 0.; i < 16.; i++) { - if(mod(i, 2.) == 0.) { - po -= vec3(1.6 + hexGap, 0., 1.); - } else { - po += vec3(-(1.6 + hexGap), 0., 1.); - } + float fftVal = fft_output[fftIndex]; + float hexHeight = 1.0 + fftVal * 3.0; - // Add individual hexagon ripples based on distance from center - int hexDist = int(length(vec2(i, j) - rippleCenter.xy)); + // Rotate individual hex tiles if needed + vec3 r = hex.local; + //r.yz *= rot2D(1.0); + r.xz *= rot2D(0.5); - //float wave = sin(hexDist * rippleFreq - u_time * rippleSpeed) * exp(-hexDist * rippleDecay); + float d1 = fHexagonCircumcircle(vec3(r.x,(r.y-hexHeight/2),r.z), vec2(hexRadius, hexHeight/2)); + res = min(res, vec2(d1,0.)); - // Apply ripple to hexagon size and position - - // float hexSize = fft_output[int(i+1)*int(j+1)]*5.0; // sin(1.5*u_time)+ wave - //float hexSize = fft_output[hexDist] * 5.0; - float hexSize = getScaledFFT(hexDist, 15.0, 0.0) * 2.0; // Adjusted multiplier - a = sdHex(po, 1. + hexSize, 0.); - //d = min(d, a); - res = opU(res, vec2(a, 2.)); - } - } - */ - // main note effect shapes - // res = opU( res, vec2( sdSphere(p- vec3(2.0 + (test.x * 2.), 12. + (test.y * 10.), 0.0), 0.2 ), 1.)); - - - float gridSize = 16.0; // or GRID if you want full size - //float hexGap = 0.2; - - for(float j = 0.; j < gridSize; j++) { - for(float i = 0.; i < gridSize; i++) { - ivec2 texSize = textureSize(u_hexGridTex, 0); - vec2 texCoord = (vec2(i, j)) / vec2(texSize); - - vec4 hexData = texture(u_hexGridTex, texCoord); // RGBA: x, y, z, dist - - vec3 hexPos = hexData.rgb; - float hexDist = hexData.a; - - // Optionally use hexDist for ripple effect with FFT - int index = clamp(int((hexDist / 34.)*512.), 0, 511); - float hexSize = getScaledFFT(index, 15. ,0.); - float a = sdHex(p - hexPos, 1.0 + hexSize, 0.0); - res = min(res, vec2(a, 1.)); - - } - } - float gridSize2 = 16.; for(float j = 0.; j < gridSize2; j++) { for(float i = 0.; i < gridSize2; i++) { @@ -166,7 +197,6 @@ vec2 mapScene(in vec3 p) { } } - return res; } @@ -175,24 +205,63 @@ vec2 mapScene(in vec3 p) { //////////////// vec3 castRay(vec3 ro, vec3 rd, inout vec3 pos) { - float t = 0.; float mat = 0.; float hit = 0.; - // Reduced from 40 to 24 steps - for(int i = 0; i < 30; i++) { + vec3 d; + float t = 0.,ad,tmax=400.; // total distance travelled + const float tolerance = 0.001; + const float Z_REPEAT_DIST = 1.; + vec2 res; + + // Raymarching + for (int i = 0; i < 50; i++) { pos = ro + rd * t; - vec2 res = mapScene(pos); - // Increase step size multiplier for faster marching - t += res.x; + res = mapScene(pos); // Get distance to objects + ad = abs(res.x); mat = res.y; - if(t > 400.) { // Reduced max distance - break; - } - if(res.x < 0.001 * t) { // Less precise hit detection - hit = 1.; + if (t > tmax) break; + if (ad < tolerance*(t*0.125 + 1.0)) { + hit = 1.0; break; } + t += res.x; // "march" the ray } + t -= Z_REPEAT_DIST*1.; + + for( int i=0; i<30; 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/2.0); // "march" the ray + } + //if (t >= tmax) { + // t= - 1.0; + // hit = 0.; + //} + //Reduced from 40 to 24 steps +// for(int i = 0; i < 30; i++) { +// pos = ro + rd * t; +// vec2 res = mapScene(pos); +// // Increase step size multiplier for faster marching +// t += res.x; +// mat = res.y; +// if(t > 400.) { // Reduced max distance +// break; +// } +// if(res.x < 0.00001 * (t*0.00125 + 1.0)) { // Less precise hit detection +// hit = 1.; +// break; +// } +// } // This will break fog effect //if (t > 100.) // t = 0.; @@ -436,7 +505,7 @@ vec3 getCameraRayDir(vec2 uv, vec3 camPos, vec3 camTarget, float fov) vec3 render(vec2 uv) { - vec3 camPos = vec3(-20.0, 20.0, -80.0); + vec3 camPos = vec3(-20.0, 20.0, -20.0); vec3 camTarget = vec3(0.0, 10.0, 0.0); // Adjust target as needed float fov = 1.0; diff --git a/src/shaders/fragment.inl b/src/shaders/fragment.inl index 75044d4..67ff9d0 100644 --- a/src/shaders/fragment.inl +++ b/src/shaders/fragment.inl @@ -1,155 +1,192 @@ // Generated with Shader Minifier 1.5.1 (https://github.com/laurentlb/Shader_Minifier/) #ifndef FRAGMENT_INL_ # define FRAGMENT_INL_ -# define VAR_fft_output "i" +# define VAR_fft_output "H" # define VAR_o "f" -# define VAR_shapes "s" +# define VAR_shapes "a" # define VAR_syncs "m" -# define VAR_test "k" -# define VAR_u_ShapesTex "d" -# define VAR_u_hexGridTex "l" +# define VAR_test "l" +# define VAR_u_ShapesTex "x" +# define VAR_u_hexGridTex "k" const char *fragment_frag = "#version 460\n" "precision mediump float;" "out vec4 f;" - "const float n=2.*acos(-1.),v=sqrt(5.)*.5+.5;" + "const float i=2.*acos(-1.),v=sqrt(5.)*.5+.5;" "layout(location=0)uniform float m[12];" - "layout(location=20)uniform float i[512];" - "layout(location=600)uniform vec3 s[15];" - "layout(location=700)uniform vec3 k;" - "layout(binding=1)uniform sampler2D l;" - "layout(binding=0)uniform sampler2D d;" - "float g=m[0];" - "float t(int v)" + "layout(location=20)uniform float H[512];" + "layout(location=600)uniform vec3 a[15];" + "layout(location=700)uniform vec3 l;" + "layout(binding=1)uniform sampler2D k;" + "layout(binding=0)uniform sampler2D x;" + "float n=m[0];" + "mat2 s()" "{" - "v=clamp(v,0,511);" - "float n=i[v];" - "return log(1.+n*15.);" + "float v=sin(.5),x=cos(.5);" + "return mat2(x,-v,v,x);" "}" - "float t(vec3 v,vec2 i)" + "float s(vec3 v,vec2 x)" "{" "v=abs(v);" - "return max(v.y-i.y,max(v.x*sqrt(3.)*.5+v.z*.5,v.z)-i.x);" + "return max(v.y-x.y,max(v.x*sqrt(3.)*.5+v.z*.5,v.z)-x.x);" + "}\n" + "#define zclamp(a)max(a,0.0)\n" + "struct HexData{vec3 local;vec2 axial;};" + "HexData s(vec3 v)" + "{" + "float x=sqrt(3.)/3.*v.x-1./3.*v.z,f=2./3.*v.z,m=round(x),l=round(f),k=round(-x-f),n=abs(m-x),a=abs(l-f);" + "x=abs(k+x+f);" + "if(n>a&&n>x)" + "m=-l-k;" + "else if(a>x)" + "l=-m-k;" + "x=sqrt(3.)*(m+l*.5);" + "f=1.5*l;" + "HexData i;" + "i.local=v-vec3(x,0,f);" + "i.axial=vec2(m,l);" + "return i;" + "}" + "struct HexData{vec3 local;vec2 axial;};" + "float s(vec2 v)" + "{" + "float x=v.x,f=v.y;" + "return max(abs(x),max(abs(f),abs(-x-f)));" "}" "vec2 t(vec3 v)" "{" "vec2 f=vec2(v.y,0);" + "HexData m=s(vec3(v.x,v.y-2.5,v.z));" + "float i=1.+H[int(clamp(s(m.axial)+1.,0.,511.))]*3.;" + "vec3 l=m.local;" + "l.xz*=s();" + "i=s(vec3(l.x,l.y-i/2,l.z),vec2(.83,i/2));" + "f=min(f,vec2(i,0));" "for(float i=0.;i<16.;i++)" - "for(float n=0.;n<16.;n++)" + "for(float l=0.;l<16.;l++)" "{" - "ivec2 d=textureSize(l,0);" - "vec2 m=vec2(n,i)/vec2(d);" - "vec4 g=texture(l,m);" - "f=min(f,vec2(t(v-g.xyz,vec2(.86,1.+t(clamp(int(g.w/34.*512.),0,511)))),1));" - "}" - "for(float i=0.;i<16.;i++)" - "for(float n=0.;n<16.;n++)" - "{" - "vec2 m=(vec2(n,i)+.5)/float(16.);" - "vec4 g=texture(d,m);" - "if(g.w<.5)" + "vec2 m=(vec2(l,i)+.5)/float(16.);" + "vec4 n=texture(x,m);" + "if(n.w<.5)" "continue;" - "f=min(f,vec2(length(v-vec3(-70.+g.x*2.,12.+g.y*80.,0))-.8,1));" + "f=min(f,vec2(length(v-vec3(-70.+n.x*2.,12.+n.y*80.,0))-.8,1));" "}" "return f;" "}" - "vec3 t(vec3 v,vec3 n,inout vec3 f)" + "vec3 s(vec3 v,vec3 x,inout vec3 f)" "{" - "float i=0.,l=0.,m=0.;" - "for(int g=0;g<30;g++)" + "float i=0.,l=0.;" + "vec3 m;" + "float n=0.,k;" + "vec2 a;" + "for(int m=0;m<50;m++)" "{" - "f=v+n*i;" - "vec2 d=t(f);" - "i+=d.x;" - "l=d.y;" - "if(i>4e2)" + "f=v+x*n;" + "a=t(f);" + "k=abs(a.x);" + "i=a.y;" + "if(n>4e2)" "break;" - "if(d.x<.001*i)" + "if(k<.001*(n*.125+1.))" "{" - "m=1.;" + "l=1.;" "break;" "}" + "n+=a.x;" "}" - "return vec3(i,l,m);" - "}" - "float t(vec3 v,vec3 i,float f)" - "{" - "float n=1.,m=.02;" - "for(int g=0;g<6;g++)" + "n-=1.;" + "for(int r=0;r<30;r++)" "{" - "if(m>f)" + "vec3 s=v+x*n;" + "a=t(s);" + "k=abs(a.x);" + "i=a.y;" + "if(k<.001)" + "{" + "l=1.;" + "f=s;" + "break;" + "}" + "if(n>4e2)" "break;" - "float l=t(v+m*i).x;" - "n=min(n,l/(4.*m));" - "m+=clamp(l,.1,.8);" - "if(n<-1.)" + "n+=min(m.x,.5);" + "}" + "return vec3(n,i,l);" + "}" + "float s(vec3 v,vec3 x,float f)" + "{" + "float i=1.,l=.02;" + "for(int m=0;m<6;m++)" + "{" + "if(l>f)" + "break;" + "float n=t(v+l*x).x;" + "i=min(i,n/(4.*l));" + "l+=clamp(n,.1,.8);" + "if(i<-1.)" "break;" "}" - "n=max(n,-1.);" - "return.25*(1.+n)*(1.+n)*(2.-n);" + "i=max(i,-1.);" + "return.25*(1.+i)*(1.+i)*(2.-i);" "}" - "vec3 x(vec3 v)" + "vec3 p(vec3 v)" "{" - "vec2 n=vec2(.01,0);" - "v=vec3(t(v+n.xyy).x-t(v-n.xyy).x,t(v+n.yxy).x-t(v-n.yxy).x,t(v+n.yyx).x-t(v-n.yyx).x);" - "return normalize(v);" + "vec2 i=vec2(.01,0);" + "return normalize(vec3(t(v+i.xyy).x-t(v-i.xyy).x,t(v+i.yxy).x-t(v-i.yxy).x,t(v+i.yyx).x-t(v-i.yyx).x));" "}" - "vec3 t(vec3 v,vec3 n,vec3 i,vec3 f,float m)" + "vec3 p(vec3 v,vec3 m,vec3 i,vec3 x,float f)" "{" - "vec3 g=vec3(.77,.26,.73);" - "v-=n;" - "float l=length(v);" + "vec3 l=vec3(.77,.26,.73);" + "v-=m;" + "float n=length(v);" "v=normalize(v);" - "float x=30./(1.+.09*l+.032*l*l),c=max(dot(f,v),0.);" + "float a=30./(1.+.09*n+.032*n*n),k=max(dot(x,v),0.);" "i=normalize(v-i);" - "vec3 e=vec3(.04);" - "e+=(1.-e)*pow(clamp(1.-max(dot(i,v),0.),0.,1.),5.);" - "l=t(n+f*.01,v,l);" - "return(g*c*x+g*pow(max(dot(f,i),0.),mix(128.,8.,m))*x*e)*l;" + "vec3 r=vec3(.04);" + "r+=(1.-r)*pow(clamp(1.-max(dot(i,v),0.),0.,1.),5.);" + "n=s(m+x*.01,v,n);" + "return(l*k*a+l*pow(max(dot(x,i),0.),mix(128.,8.,f))*a*r)*n;" "}" - "vec3 t(vec3 v,vec3 f,vec3 i,float n)" + "vec3 p(vec3 v,vec3 i,vec3 x,float f)" "{" - "float m=.01;" - "vec3 g=vec3(0);" - "if(n==0.)" - "g=vec3(.8314,.2941,.2941),m=.1;" - "else if(n==1.)" - "g=vec3(.6196,.6118,.6118),m=.7;" - "else if(n==2.)" - "g=vec3(.3255,.4784,.3255),m=.2;" - "else if(n==3.)" - "g=vec3(.2471,.3059,.6314),m=1.;" - "else if(n==4.)" - "g=vec3(.9961,1,.9922),m=.1;" - "else if(n==5.)" - "g=vec3(.9961,1,.9922),m=.3;" - "vec3 l=vec3(0);" - "l+=t(vec3(0,40,-10),v,i,f,m);" - "l+=t(vec3(0,20,15),v,i,f,m);" - "l+=vec3(.08,.62,.75)*clamp(dot(f,normalize(vec3(0,1,-3)*vec3(0,-1,-2))),0.,1.)*.8;" - "return g*max(vec3(0),l);" + "float l=.01;" + "vec3 m=vec3(0);" + "if(f==0.)" + "m=vec3(.8314,.2941,.2941),l=.1;" + "else if(f==1.)" + "m=vec3(.6196,.6118,.6118),l=.7;" + "else if(f==2.)" + "m=vec3(.3255,.4784,.3255),l=.2;" + "else if(f==3.)" + "m=vec3(.2471,.3059,.6314),l=1.;" + "else if(f==4.)" + "m=vec3(.9961,1,.9922),l=.1;" + "else if(f==5.)" + "m=vec3(.9961,1,.9922),l=.3;" + "v=vec3(0)+p(vec3(0,40,-10),v,x,i,l)+p(vec3(0,20,15),v,x,i,l)+vec3(.08,.62,.75)*clamp(dot(i,normalize(vec3(0,1,-3)*vec3(0,-1,-2))),0.,1.)*.8;" + "return m*max(vec3(0),v);" "}" - "vec3 t(vec2 n,vec3 v)" + "vec3 p(vec2 v,vec3 f)" "{" - "v=normalize(vec3(0,10,0)-v);" - "vec3 m=normalize(cross(vec3(0,1,0),v));" - "return normalize(v+n.x*m+n.y*cross(v,m));" + "f=normalize(vec3(0,10,0)-f);" + "vec3 l=normalize(cross(vec3(0,1,0),f));" + "return normalize(f+v.x*l+v.y*cross(f,l));" "}" - "vec3 t(vec2 v)" + "vec3 p(vec2 v)" "{" - "vec3 n=vec3(-20,20,-80),f=t(v,n),i=vec3(0),l=vec3(0);" - "n=t(n,f,l);" - "if(n.x>0.)" + "vec3 f=vec3(-20,20,-20),l=p(v,f),i=vec3(0),x=vec3(0);" + "f=s(f,l,x);" + "if(f.x>0.)" "{" - "vec3 v=x(l);" - "i=t(l,v,f,n.y);" + "vec3 v=p(x);" + "i=p(x,v,l,f.y);" "}" - "return i*exp(-n.x*.01)+mix(i,mix(vec3(.2667,.2941,.3451),vec3(.302,.3176,.3725),pow(max(dot(f,vec3(0,-.5,1.8)),0.),clamp(m[1]+m[2]+m[3],0.,1.)*5.)),1.-exp(-n.x*.01))*(1.-exp(-n.x*.01));" + "return i*exp(-f.x*.01)+mix(i,mix(vec3(.2667,.2941,.3451),vec3(.302,.3176,.3725),pow(max(dot(l,vec3(0,-.5,1.8)),0.),clamp(m[1]+m[2]+m[3],0.,1.)*5.)),1.-exp(-f.x*.01))*(1.-exp(-f.x*.01));" "}" "void main()" "{" - "vec3 v=t(gl_FragCoord.xy*vec2(.00104166667,.00185185185)-1.);" + "vec3 v=p(gl_FragCoord.xy*vec2(.00104166667,.00185185185)-1.);" "f=vec4(v,1);" "}";