From e00ae27d46d8775905b17138e7c549c0645e0f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teemu=20J=C3=A4rvisalo?= Date: Thu, 31 Jul 2025 15:45:30 +0300 Subject: [PATCH] partikkeli-efekti, nuottiefekti kommentoituna --- src/main.cpp | 162 +++++++++++++++++++++-------------- src/shaders/fragment.frag | 79 ++++++++++++++--- src/shaders/fragment.inl | 175 ++++++++++++++++++-------------------- 3 files changed, 249 insertions(+), 167 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c3ef5a5..2cccc31 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -127,41 +127,8 @@ int __cdecl main(int argc, char* argv[]) static float fft_output[FFT_SIZE / 2]; // Magnitudes static float fft_uniform[FFT_SIZE / 4]; - // main note effect - boolean beenPlaying = false; - const int SHAPES_SIZE = 15; - float shapeIncrement = 0.15f; - /** - * Definition of shape with 3 parameters in a vec3 - * - * h position, v position, length - * - */ - float vec3ShapeArray[5][3] = { - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f } - }; - float test[3] = { 0.0f, 0.0f, 0.0f }; // test float of one shape - - int currentShape = 0; // mark location which shape we are currently building - - boolean isPlaying = false; - - float lastPlayPos = 0; - float lastNote = 0.0f; - - /*GLfloat shapes[5][3] = { - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f } - };*/ struct Vec3 { @@ -173,15 +140,18 @@ int __cdecl main(int argc, char* argv[]) #define SHAPES 16 #define SHAPES_TEX_SIZE (SHAPES * SHAPES * 4) -#define SHAPES_TOTAL (SHAPES * SHAPES) #define MAX_DISTANCE 100.f +#define PARTICLES 16 +#define PARTICLES_TEX_SIZE (PARTICLES * PARTICLES * 4) +#define PARTICLES_DISTANCE 80.f + PFNGLUNIFORM1FVPROC glUniform1fvProc = ((PFNGLUNIFORM1FVPROC)wglGetProcAddress("glUniform1fv")); PFNGLACTIVETEXTUREPROC glActiveTexture = ((PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture")); PFNGLUNIFORM1IPROC glUniform1i = ((PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i")); PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = ((PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation")); - GLuint hexGridTex, ShapesTex; + GLuint hexGridTex, shapesTex, particlesTex; glGenTextures(1, &hexGridTex); glBindTexture(GL_TEXTURE_2D, hexGridTex); @@ -192,9 +162,9 @@ 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); - - glGenTextures(1, &ShapesTex); - glBindTexture(GL_TEXTURE_2D, ShapesTex); + /* + glGenTextures(1, &shapesTex); + glBindTexture(GL_TEXTURE_2D, shapesTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SHAPES, SHAPES, 0, GL_RGBA, GL_FLOAT, nullptr); @@ -202,6 +172,28 @@ int __cdecl main(int argc, char* argv[]) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + */ + + glGenTextures(1, &particlesTex); + glBindTexture(GL_TEXTURE_2D, particlesTex); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SHAPES, SHAPES, 0, GL_RGBA, GL_FLOAT, nullptr); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + static float shapesData[SHAPES_TEX_SIZE]; + int currentShape = 0; // mark location which shape we are currently building + float shapeIncrement = 0.15f; + float shapeLastNote = 0.0f; + + static float particlesData[PARTICLES_TEX_SIZE]; + static float particlesData2[PARTICLES*PARTICLES]; // additional value for particle distance + int currentParticle = 0; // mark location which shape we are currently building + float particleIncrement = 1.0f; + float particleLastNote = 0.0f; do { @@ -279,7 +271,7 @@ int __cdecl main(int argc, char* argv[]) } - + /* ////////////////////////////////////////////////////// // Shape builder ////////////////////////////////////////////////////// @@ -287,33 +279,28 @@ int __cdecl main(int argc, char* argv[]) // if sound is playing, start a shape, if shape is already started - add length // if sound has stopped, end shape // if shape is finished, move shape forward - static float shapesData[SHAPES_TEX_SIZE]; - float captureSync = syncs[5]; - - bool shapeJustFinished = false; - bool shapeJustStarted = false; + float shapeCaptureSync = syncs[5]; // Detect note change to start a new shape - bool noteChanged = (captureSync - lastNote) * (captureSync - lastNote) > 0.0001f; - lastNote = captureSync; - + bool shapeNoteChanged = (shapeCaptureSync - shapeLastNote) * (shapeCaptureSync - shapeLastNote) > 0.0001f; + shapeLastNote = shapeCaptureSync; // If note changed and value is significant, start new shape - if (captureSync > 0.001f && noteChanged) { + if (shapeCaptureSync > 0.001f && shapeNoteChanged) { int index = currentShape * 4; // Reset and activate current shape shapesData[index + 0] = 0.0f; // x start - shapesData[index + 1] = captureSync; // y from audio + shapesData[index + 1] = shapeCaptureSync; // y from audio shapesData[index + 2] = 1.0f; // z (unused or length) shapesData[index + 3] = 1.0f; // active // Advance to next shape slot (circular) - currentShape = (currentShape + 1) % SHAPES_TOTAL; + currentShape = (currentShape + 1) % (SHAPES*SHAPES); } // Move active shapes - for (int i = 0; i < SHAPES_TOTAL; ++i) { + for (int i = 0; i < SHAPES*SHAPES; ++i) { int index = i * 4; // Check if shape is active @@ -339,22 +326,71 @@ int __cdecl main(int argc, char* argv[]) // Bind and update u_ShapesTex glActiveTexture(GL_TEXTURE0 + 2); - glBindTexture(GL_TEXTURE_2D, ShapesTex); + glBindTexture(GL_TEXTURE_2D, shapesTex); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, SHAPES, SHAPES, GL_RGBA, GL_FLOAT, shapesData); glUniform1i(glGetUniformLocation(pidMain, "u_ShapesTex"), 2); - - - /* - float flatShapes[15] = { - vec3ShapeArray[0][0], vec3ShapeArray[0][1], vec3ShapeArray[0][2], - vec3ShapeArray[1][0], vec3ShapeArray[1][1], vec3ShapeArray[1][2], - vec3ShapeArray[2][0], vec3ShapeArray[2][1], vec3ShapeArray[2][2], - vec3ShapeArray[3][0], vec3ShapeArray[3][1], vec3ShapeArray[3][2], - vec3ShapeArray[4][0], vec3ShapeArray[4][1], vec3ShapeArray[4][2] - }; */ - + ////////////////////////////////////////////////////// + // Particles Builder + ////////////////////////////////////////////////////// + + // if sound is playing, start a shape, if shape is already started - add length + // if sound has stopped, end shape + // if shape is finished, move shape forward + float particleCaptureSync = syncs[5]; + + // Detect note change to start a new shape + bool particleNoteChanged = (particleCaptureSync - particleLastNote) * (particleCaptureSync - particleLastNote) > 0.0001f; + particleLastNote = particleCaptureSync; + + // If note changed and value is significant, start new shape + if (particleCaptureSync > 0.001f && particleNoteChanged) { + int index = currentParticle * 4; + + // Reset and activate current shape + particlesData[index + 0] = 0.0f; // x offset + particlesData[index + 1] = 0.0f; // y offset + particlesData[index + 2] = 0.0f; // z distance + particlesData[index + 3] = 1.0f; // a active + + //particlesData2[currentParticle] = 0.0f; // reset progress/time! + + // Advance to next shape slot (circular) + currentParticle = (currentParticle + 1) % (PARTICLES * PARTICLES); + } + + // Move active shapes + for (int i = 0; i < (PARTICLES * PARTICLES); ++i) { + int index = i * 4; + + // Check if shape is active + if (particlesData[index + 3] > 0.5f) { + // Move shape + particlesData[index + 2] += particleIncrement; + + // Update y (optional, reflect live audio) + //shapesData[index + 1] = captureSync; + + // Optional: grow z value to show duration + //shapesData[index + 2] += shapeIncrement * 0.2f; + + // If x exceeds max distance, deactivate and reset + if (particlesData[index + 2] > PARTICLES_DISTANCE) { + particlesData[index + 0] = 0.0f; + particlesData[index + 1] = 0.0f; + particlesData[index + 2] = 0.0f; + particlesData[index + 3] = 0.0f; // inactive + } + } + } + + // Bind and update u_ParticlesTex + glActiveTexture(GL_TEXTURE0 + 3); + glBindTexture(GL_TEXTURE_2D, particlesTex); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, PARTICLES, PARTICLES, GL_RGBA, GL_FLOAT, particlesData); + glUniform1i(glGetUniformLocation(pidMain, "u_ParticlesTex"), 3); + //glUniform1fvProc(700, PARTICLES*PARTICLES, particlesData2); //PFNGLUNIFORM3FVPROC glUniform3fvProc = ((PFNGLUNIFORM3FVPROC)wglGetProcAddress("glUniform3fv")); //glUniform3fvProc(600, 1, flatShapes); // array of shapes diff --git a/src/shaders/fragment.frag b/src/shaders/fragment.frag index 1c8c117..ec9e867 100644 --- a/src/shaders/fragment.frag +++ b/src/shaders/fragment.frag @@ -7,9 +7,10 @@ const float PHI = sqrt(5.) * 0.5 + 0.5; layout(location = 0) uniform float syncs[12]; layout(location = 20) uniform float fft_output[512]; // FFT_SIZE / 4 layout(location = 600) uniform vec3 shapes[15]; // shapes - x = horizontal position, y = vertical position, z = length -layout(location = 700) uniform vec3 test; // shapes test +//layout(location = 700) uniform float particlesData2[256]; // additional particles data for distance layout(binding = 1) uniform sampler2D u_hexGridTex; //uniform sampler2D u_fft_texture; -layout(binding = 0) uniform sampler2D u_ShapesTex; // uniform sampler2D shapes texture +//layout(binding = 0) uniform sampler2D u_ShapesTex; // uniform sampler2D shapes texture +layout(binding = 3) uniform sampler2D u_ParticlesTex; // uniform sampler2D particles texture float u_time = syncs[0]; vec3 palette(float t){ @@ -20,6 +21,11 @@ vec3 palette(float t){ return a+b*cos(6.28318*(c*t+d)); } +// Or 2D version +float hash(vec2 p) { + return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123); +} + vec2 getUV() { const vec2 scale = vec2(0.00104166667, 0.00185185185); return gl_FragCoord.xy * scale - 1.0; @@ -126,7 +132,7 @@ vec2 mapScene(in vec3 p) { // 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; @@ -144,11 +150,11 @@ vec2 mapScene(in vec3 p) { 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.)); - + res = opU(res, vec2(a, 1.)); } } - + */ + /* float gridSize2 = 16.; for(float j = 0.; j < gridSize2; j++) { for(float i = 0.; i < gridSize2; i++) { @@ -162,11 +168,52 @@ vec2 mapScene(in vec3 p) { float a = sdSphere(shapePos, 0.8); - res = min(res, vec2(a, 1.)); + res = opU(res, vec2(a, 1.)); + } + } + */ + + float maxRadius = 40.; // Circle radius + float sphereRadius = 0.7; + int index = 0; + + float gridSize3 = 16.; + for(float j = 0; j < gridSize3; j++) { + for(float i = 0; i < gridSize3; i++) { + vec2 texCoord = (vec2(i, j) + 0.5) / float(gridSize3); + vec4 particleData = texture(u_ParticlesTex, texCoord); // RGBA: x, y, distance, active + float particleActive = particleData.a; + + if(particleData.z < 0.5) continue; + + // Map param to angle + float particleStartPos = hash(vec2(j, i)) * 2.0 * PI; + + // Direction from center to initial circle position (in XY plane) + vec3 dir = normalize(vec3(cos(particleStartPos), 0.0, sin(particleStartPos))); // XZ direction + + // Compute current radius: shrinking over time + //float r = particleDist; + //if(particleDist > maxRadius) { + // particleDist = maxRadius; + //} + + float r = max(maxRadius - particleData.z, -maxRadius); + + float offsetFactor = 15.; + vec3 particleOffset = vec3(hash(vec2(i, j)) * offsetFactor , 4., hash(vec2(j, i)) * offsetFactor); // particle offset + + // Final object position = center (offset) + radial movement + vec3 center = particleOffset; // Circle center + vec3 objPos = center + dir * r; // Object slides inward + res = opU(res, vec2(sdSphere(p - objPos, sphereRadius), 1.)); + + index++; } } - + //res = opU(res, vec2(sdSphere(p - vec3(.0, 4., .0), 1.0), .1)); + return res; } @@ -185,7 +232,7 @@ vec3 castRay(vec3 ro, vec3 rd, inout vec3 pos) { // Increase step size multiplier for faster marching t += res.x; mat = res.y; - if(t > 400.) { // Reduced max distance + if(t > 600.) { // Reduced max distance break; } if(res.x < 0.001 * t) { // Less precise hit detection @@ -436,7 +483,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(-10.0, 20.0, -20.0); vec3 camTarget = vec3(0.0, 10.0, 0.0); // Adjust target as needed float fov = 1.0; @@ -451,10 +498,20 @@ vec3 render(vec2 uv) { vec3 nor = calcNormal(hitPos); col = shading(hitPos, nor, rayDir, t.y); } + /* + //glow from the bottom + vec3 bGlowColor = palette(clamp((syncs[1] + syncs[2] + syncs[3]), 0., 1.)); // color change + float bGlowDistance = 0.3; + vec3 p = camPos + t.x * rayDir; + vec3 bGlowLevel = bGlowColor * exp(-(p.y + 0.0) / bGlowDistance) * 9900.; + col += bGlowLevel; + col = clamp(mix(bGlowLevel, col, t.z), 0.0, 1.0); + + */ + // distance fog + bass thunder float fogAmount = 0.01; col = col *exp(-t.x*fogAmount) + applyFog(col, t.x, rayDir, vec3(0., -0.5, 1.8), fogAmount) * (1.0-exp(-t.x*fogAmount)); - return col; } diff --git a/src/shaders/fragment.inl b/src/shaders/fragment.inl index 75044d4..8780ad5 100644 --- a/src/shaders/fragment.inl +++ b/src/shaders/fragment.inl @@ -1,155 +1,144 @@ // 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 "n" # define VAR_o "f" # define VAR_shapes "s" # define VAR_syncs "m" -# define VAR_test "k" -# define VAR_u_ShapesTex "d" -# define VAR_u_hexGridTex "l" +# define VAR_u_ParticlesTex "d" +# 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=20)uniform float n[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;" + "layout(binding=1)uniform sampler2D k;" + "layout(binding=3)uniform sampler2D d;" "float g=m[0];" - "float t(int v)" + "float t(vec2 v)" "{" - "v=clamp(v,0,511);" - "float n=i[v];" - "return log(1.+n*15.);" + "return fract(sin(dot(v,vec2(127.1,311.7)))*43758.5453123);" "}" - "float t(vec3 v,vec2 i)" + "vec2 t(vec2 f,vec2 i)" "{" - "v=abs(v);" - "return max(v.y-i.y,max(v.x*sqrt(3.)*.5+v.z*.5,v.z)-i.x);" + "return f.x4e2)" + "i=v+f*l;" + "vec2 g=t(i);" + "l+=g.x;" + "m=g.y;" + "if(l>6e2)" "break;" - "if(d.x<.001*i)" + "if(g.x<.001*l)" "{" - "m=1.;" + "y=1.;" "break;" "}" "}" - "return vec3(i,l,m);" + "return vec3(l,m,y);" "}" - "float t(vec3 v,vec3 i,float f)" + "float t(vec3 v,vec3 f,float i)" "{" - "float n=1.,m=.02;" - "for(int g=0;g<6;g++)" + "float l=1.,m=.02;" + "for(int n=0;n<6;n++)" "{" - "if(m>f)" + "if(m>i)" "break;" - "float l=t(v+m*i).x;" - "n=min(n,l/(4.*m));" - "m+=clamp(l,.1,.8);" - "if(n<-1.)" + "float g=t(v+m*f).x;" + "l=min(l,g/(4.*m));" + "m+=clamp(g,.1,.8);" + "if(l<-1.)" "break;" "}" - "n=max(n,-1.);" - "return.25*(1.+n)*(1.+n)*(2.-n);" + "l=max(l,-1.);" + "return.25*(1.+l)*(1.+l)*(2.-l);" "}" "vec3 x(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 f=vec2(.01,0);" + "return normalize(vec3(t(v+f.xyy).x-t(v-f.xyy).x,t(v+f.yxy).x-t(v-f.yxy).x,t(v+f.yyx).x-t(v-f.yyx).x));" "}" - "vec3 t(vec3 v,vec3 n,vec3 i,vec3 f,float m)" + "vec3 t(vec3 v,vec3 l,vec3 f,vec3 m,float i)" "{" "vec3 g=vec3(.77,.26,.73);" - "v-=n;" - "float l=length(v);" + "v-=l;" + "float n=length(v);" "v=normalize(v);" - "float x=30./(1.+.09*l+.032*l*l),c=max(dot(f,v),0.);" - "i=normalize(v-i);" + "float x=30./(1.+.09*n+.032*n*n),y=max(dot(m,v),0.);" + "f=normalize(v-f);" "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;" + "e+=(1.-e)*pow(clamp(1.-max(dot(f,v),0.),0.,1.),5.);" + "n=t(l+m*.01,v,n);" + "return(g*y*x+g*pow(max(dot(m,f),0.),mix(128.,8.,i))*x*e)*n;" "}" - "vec3 t(vec3 v,vec3 f,vec3 i,float n)" + "vec3 t(vec3 v,vec3 f,vec3 m,float l)" "{" - "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 i=.01;" + "vec3 n=vec3(0);" + "if(l==0.)" + "n=vec3(.8314,.2941,.2941),i=.1;" + "else if(l==1.)" + "n=vec3(.6196,.6118,.6118),i=.7;" + "else if(l==2.)" + "n=vec3(.3255,.4784,.3255),i=.2;" + "else if(l==3.)" + "n=vec3(.2471,.3059,.6314),i=1.;" + "else if(l==4.)" + "n=vec3(.9961,1,.9922),i=.1;" + "else if(l==5.)" + "n=vec3(.9961,1,.9922),i=.3;" + "v=vec3(0)+t(vec3(0,40,-10),v,m,f,i)+t(vec3(0,20,15),v,m,f,i)+vec3(.08,.62,.75)*clamp(dot(f,normalize(vec3(0,1,-3)*vec3(0,-1,-2))),0.,1.)*.8;" + "return n*max(vec3(0),v);" "}" - "vec3 t(vec2 n,vec3 v)" + "vec3 t(vec2 f,vec3 v)" "{" "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));" + "vec3 i=normalize(cross(vec3(0,1,0),v));" + "return normalize(v+f.x*i+f.y*cross(v,i));" "}" - "vec3 t(vec2 v)" + "vec3 x(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(-10,20,-20),l=t(v,f),i=vec3(0),n=vec3(0);" + "f=t(f,l,n);" + "if(f.x>0.)" "{" - "vec3 v=x(l);" - "i=t(l,v,f,n.y);" + "vec3 v=x(n);" + "i=t(n,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=x(gl_FragCoord.xy*vec2(.00104166667,.00185185185)-1.);" "f=vec4(v,1);" "}";