diff --git a/src/main.cpp b/src/main.cpp index 435c64a..c3ef5a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -171,6 +171,38 @@ int __cdecl main(int argc, char* argv[]) #define GRID 32 #define HEX_TEX_SIZE (GRID * GRID * 4) // RGBA: 4 floats per texel +#define SHAPES 16 +#define SHAPES_TEX_SIZE (SHAPES * SHAPES * 4) +#define SHAPES_TOTAL (SHAPES * SHAPES) +#define MAX_DISTANCE 100.f + + PFNGLUNIFORM1FVPROC glUniform1fvProc = ((PFNGLUNIFORM1FVPROC)wglGetProcAddress("glUniform1fv")); + PFNGLACTIVETEXTUREPROC glActiveTexture = ((PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture")); + PFNGLUNIFORM1IPROC glUniform1i = ((PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i")); + PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = ((PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation")); + + GLuint hexGridTex, ShapesTex; + glGenTextures(1, &hexGridTex); + glBindTexture(GL_TEXTURE_2D, hexGridTex); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, GRID, GRID, 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); + + + glGenTextures(1, &ShapesTex); + glBindTexture(GL_TEXTURE_2D, ShapesTex); + + 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); + do { direct_sound_buffer->GetCurrentPosition((DWORD*)&playCursor, NULL); @@ -246,6 +278,8 @@ int __cdecl main(int argc, char* argv[]) syncs[i + 1] = syncBuf[(playCursor / (2 * sizeof(SUsample)) >> 8) * SU_NUMSYNCS + i]; } + + ////////////////////////////////////////////////////// // Shape builder ////////////////////////////////////////////////////// @@ -253,50 +287,64 @@ 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]; - if (captureSync >= 0.001f) { - isPlaying = true; + bool shapeJustFinished = false; + bool shapeJustStarted = false; + + // Detect note change to start a new shape + bool noteChanged = (captureSync - lastNote) * (captureSync - lastNote) > 0.0001f; + lastNote = captureSync; + + + // If note changed and value is significant, start new shape + if (captureSync > 0.001f && noteChanged) { + 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 + 2] = 1.0f; // z (unused or length) + shapesData[index + 3] = 1.0f; // active + + // Advance to next shape slot (circular) + currentShape = (currentShape + 1) % SHAPES_TOTAL; } - if (isPlaying) { - // vec3ShapeArray[currentShape][1] = captureSync; - // vec3ShapeArray[currentShape][2] = vec3ShapeArray[currentShape][2] + shapeIncrement; + // Move active shapes + for (int i = 0; i < SHAPES_TOTAL; ++i) { + int index = i * 4; - test[0] = test[0] + shapeIncrement; // x position - test[1] = captureSync; // y position - test[2] = 0.3f; // length - } + // Check if shape is active + if (shapesData[index + 3] > 0.5f) { + // Move shape right + shapesData[index + 0] += shapeIncrement; + // Update y (optional, reflect live audio) + //shapesData[index + 1] = captureSync; - // when note changes -- reset - if (lastNote != captureSync) { - test[0] = 0.0f; - test[1] = 0.1f; - lastNote = captureSync; - } + // Optional: grow z value to show duration + //shapesData[index + 2] += shapeIncrement * 0.2f; - // shape mover, if the shape isnt the current one - move it - - for (int i = 0; i < SHAPES_SIZE; ++i) { - if (i != currentShape) { - vec3ShapeArray[i][0] = vec3ShapeArray[i][0] + shapeIncrement; + // If x exceeds max distance, deactivate and reset + if (shapesData[index + 0] > MAX_DISTANCE) { + shapesData[index + 0] = 0.0f; + shapesData[index + 1] = 0.0f; + shapesData[index + 2] = 0.0f; + shapesData[index + 3] = 0.0f; // inactive + } } } - beenPlaying = isPlaying; + // Bind and update u_ShapesTex + glActiveTexture(GL_TEXTURE0 + 2); + 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); - // go through the array and start from the first when all shapes have been used - if (beenPlaying) { - if (currentShape <= SHAPES_SIZE) { - ++currentShape; - } - else { - currentShape = 0; - } - } - + + /* float flatShapes[15] = { vec3ShapeArray[0][0], vec3ShapeArray[0][1], vec3ShapeArray[0][2], vec3ShapeArray[1][0], vec3ShapeArray[1][1], vec3ShapeArray[1][2], @@ -304,21 +352,25 @@ int __cdecl main(int argc, char* argv[]) vec3ShapeArray[3][0], vec3ShapeArray[3][1], vec3ShapeArray[3][2], vec3ShapeArray[4][0], vec3ShapeArray[4][1], vec3ShapeArray[4][2] }; + */ - PFNGLUNIFORM3FVPROC glUniform3fvProc = ((PFNGLUNIFORM3FVPROC)wglGetProcAddress("glUniform3fv")); - glUniform3fvProc(600, 1, flatShapes); // array of shapes - glUniform3fvProc(700, 1, test); // test shape + + + //PFNGLUNIFORM3FVPROC glUniform3fvProc = ((PFNGLUNIFORM3FVPROC)wglGetProcAddress("glUniform3fv")); + //glUniform3fvProc(600, 1, flatShapes); // array of shapes + //glUniform3fvProc(700, 1, test); // test shape - PFNGLUNIFORM1FVPROC glUniform1fvProc = ((PFNGLUNIFORM1FVPROC)wglGetProcAddress("glUniform1fv")); + glUniform1fvProc(0, SU_NUMSYNCS + 1, syncs); glUniform1fvProc(20, FFT_SIZE / 4, fft_uniform); - glRects(-1, -1, 1, 1); - PFNGLACTIVETEXTUREPROC glActiveTexture = ((PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture")); - PFNGLUNIFORM1IPROC glUniform1i = ((PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i")); - PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = ((PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation")); + + ////////////////////////////////////////////////////// + // Hex Grid Builder + ////////////////////////////////////////////////////// + static float hexGridData[HEX_TEX_SIZE]; @@ -357,22 +409,14 @@ int __cdecl main(int argc, char* argv[]) hexGridData[idx + 3] = hexDist; } } - - GLuint hexGridTex; - glGenTextures(1, &hexGridTex); + + // Bind and update u_hexGridTex + glActiveTexture(GL_TEXTURE0 + 1); glBindTexture(GL_TEXTURE_2D, hexGridTex); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GRID, GRID, GL_RGBA, GL_FLOAT, hexGridData); + glUniform1i(glGetUniformLocation(pidMain, "u_hexGridTex"), 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, GRID, GRID, 0, GL_RGBA, GL_FLOAT, hexGridData); - - - 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); - - glActiveTexture(GL_TEXTURE0 + 2); - glUniform1i(glGetUniformLocation(pidMain, "u_hexGridTex"), 2); - + glRects(-1, -1, 1, 1); // render "post process" using the opengl backbuffer #if POST_PASS diff --git a/src/shaders/fragment.frag b/src/shaders/fragment.frag index 7a1e685..1c8c117 100644 --- a/src/shaders/fragment.frag +++ b/src/shaders/fragment.frag @@ -8,7 +8,8 @@ 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 -uniform sampler2D u_hexGridTex; //uniform sampler2D u_fft_texture; +layout(binding = 1) uniform sampler2D u_hexGridTex; //uniform sampler2D u_fft_texture; +layout(binding = 0) uniform sampler2D u_ShapesTex; // uniform sampler2D shapes texture float u_time = syncs[0]; vec3 palette(float t){ @@ -123,15 +124,14 @@ 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.)); + // 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 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++) { + 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); @@ -148,6 +148,24 @@ vec2 mapScene(in vec3 p) { } } + + float gridSize2 = 16.; + for(float j = 0.; j < gridSize2; j++) { + for(float i = 0.; i < gridSize2; i++) { + vec2 texCoord = (vec2(i, j) + 0.5) / float(gridSize2); + vec4 shapeData = texture(u_ShapesTex, texCoord); // RGBA: x, y, length, active + + float shapeActive = shapeData.a; + if(shapeActive < 0.5) continue; + + vec3 shapePos = p - vec3(-70.0 + (shapeData.x * 2.), 12. + (shapeData.y * 80.), 0.0); + + float a = sdSphere(shapePos, 0.8); + + res = min(res, vec2(a, 1.)); + } + } + return res; } @@ -167,7 +185,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 > 100.) { // Reduced max distance + if(t > 400.) { // Reduced max distance break; } if(res.x < 0.001 * t) { // Less precise hit detection @@ -175,8 +193,9 @@ vec3 castRay(vec3 ro, vec3 rd, inout vec3 pos) { break; } } - if (t > 100.) - t = 0.; + // This will break fog effect + //if (t > 100.) + // t = 0.; return vec3(t, mat, hit); } @@ -237,22 +256,28 @@ vec3 addPointLight(vec3 lightPos, vec3 lightColor, float intensity, vec3 worldPo return (diffuse + specular * fresnel) * shadow; } -vec3 addPointLightNoShadow(vec3 lightPos, vec3 lightColor, float intensity, vec3 worldPos, vec3 viewDir, vec3 normal, float roughness) { +vec3 applyFog(vec3 col, float t, vec3 rd, vec3 lightDir, float b ) { + + float syncsBass = clamp((syncs[1] + syncs[2] + syncs[3]), 0., 1.); + + float fogAmount = 1.0 - exp(-t*b); + float sunAmount = max( dot(rd, lightDir), 0.0 ); + vec3 fogColor = mix( vec3(0.2667, 0.2941, 0.3451), // blue + vec3(0.302, 0.3176, 0.3725), // yellow + pow(sunAmount, syncsBass * 5.0) ); + return mix( col, fogColor, fogAmount ); +} + +// Point light with no shadow and radius based falloff +vec3 addPointLightNoShadow(vec3 lightPos, vec3 lightColor, float intensity, float radius, vec3 worldPos, vec3 viewDir, vec3 normal, float roughness) { // Light vector from surface to light vec3 lightDir = lightPos - worldPos; float lightDistance = length(lightDir); lightDir = normalize(lightDir); - float a = 0.; - float minLight = 0.01; - float radius = 3.4; - float b = 1.0 / (radius*radius * minLight); - - // Attenuation (quadratic falloff) + // Attenuation (radius based falloff) float attenuation = clamp(intensity - lightDistance*lightDistance/(radius*radius), 0.0, 1.0); - - // Diffuse lighting (Lambert) float NdotL = max(dot(normal, lightDir), 0.0); vec3 diffuse = lightColor * NdotL * attenuation; @@ -323,10 +348,11 @@ vec3 shading(vec3 v, vec3 n, vec3 dir, float material) { } vec3 lights = vec3(0.); - //lights += addPointLight(vec3(0., 40.0, -10.), vec3(0.77, 0.26, 0.73), 30.0, v, dir, n, shininess); - //lights += addPointLight(vec3(0., 20.0, 15.), vec3(0.77, 0.26, 0.73), 30.0, v, dir, n, shininess); + lights += addPointLight(vec3(0., 40.0, -10.), vec3(0.77, 0.26, 0.73), 30.0, v, dir, n, shininess); + lights += addPointLight(vec3(0., 20.0, 15.), vec3(0.77, 0.26, 0.73), 30.0, v, dir, n, shininess); // LIGHTS IN HEX GRID PATTERN + /* float gridsize = 16.0; // or GRID if you want full size vec3 p = vec3(0.); for(float j = 0.; j < gridsize; j++) { @@ -344,9 +370,10 @@ vec3 shading(vec3 v, vec3 n, vec3 dir, float material) { float hexSize = getScaledFFT(index, 15. ,0.); //float a = sdHex(p - hexPos, 1.0 + hexSize, 0.0); - lights += addPointLightNoShadow(vec3(hexPos.x, (hexPos.y + hexSize) + 2., hexPos.z), palette(hexSize* 1.5), clamp(hexSize * 5., 0., 1.) ,v, dir, n, shininess); + lights += addPointLightNoShadow(vec3(hexPos.x, (hexPos.y + hexSize) + 2., hexPos.z), palette(hexSize* 1.5), clamp(hexSize * 5., 0., 1.), 3.4 ,v, dir, n, shininess); } } + */ vec3 lightDir = vec3(0., 1., -3); //float sun_dif = clamp(dot(n, lightDir), 0., 1.); @@ -356,7 +383,9 @@ vec3 shading(vec3 v, vec3 n, vec3 dir, float material) { float ind = clamp(dot(n, normalize(lightDir * vec3(.0, -1.0, -2.0))), 0.0, 1.0); lights += vec3(0.08, 0.62, 0.75) * ind * 0.8; - return outMaterial * max(vec3(0.), lights); + outMaterial *= max(vec3(0.), lights); // output with lights; + + return outMaterial; } vec3 postProcess(vec3 col) { @@ -407,8 +436,8 @@ vec3 getCameraRayDir(vec2 uv, vec3 camPos, vec3 camTarget, float fov) vec3 render(vec2 uv) { - vec3 camPos = vec3(-10.0, 20.0, -20.0); - vec3 camTarget = vec3(0.0, -1.0, 10.0); // Adjust target as needed + vec3 camPos = vec3(-20.0, 20.0, -80.0); + vec3 camTarget = vec3(0.0, 10.0, 0.0); // Adjust target as needed float fov = 1.0; vec3 rayDir = getCameraRayDir(uv, camPos, camTarget, fov); @@ -423,6 +452,9 @@ vec3 render(vec2 uv) { col = shading(hitPos, nor, rayDir, t.y); } + 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 adb99d1..75044d4 100644 --- a/src/shaders/fragment.inl +++ b/src/shaders/fragment.inl @@ -1,28 +1,30 @@ // Generated with Shader Minifier 1.5.1 (https://github.com/laurentlb/Shader_Minifier/) #ifndef FRAGMENT_INL_ # define FRAGMENT_INL_ -# define VAR_fft_output "m" -# define VAR_o "v" -# define VAR_shapes "l" -# define VAR_syncs "i" +# define VAR_fft_output "i" +# define VAR_o "f" +# define VAR_shapes "s" +# define VAR_syncs "m" # define VAR_test "k" -# define VAR_u_hexGridTex "c" +# define VAR_u_ShapesTex "d" +# define VAR_u_hexGridTex "l" const char *fragment_frag = "#version 460\n" "precision mediump float;" - "out vec4 v;" - "const float n=2.*acos(-1.),f=sqrt(5.)*.5+.5;" - "layout(location=0)uniform float i[12];" - "layout(location=20)uniform float m[512];" - "layout(location=600)uniform vec3 l[15];" + "out vec4 f;" + "const float n=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;" - "uniform sampler2D c;" - "float s=i[0];" + "layout(binding=1)uniform sampler2D l;" + "layout(binding=0)uniform sampler2D d;" + "float g=m[0];" "float t(int v)" "{" "v=clamp(v,0,511);" - "float n=m[v];" + "float n=i[v];" "return log(1.+n*15.);" "}" "float t(vec3 v,vec2 i)" @@ -30,115 +32,125 @@ const char *fragment_frag = "v=abs(v);" "return max(v.y-i.y,max(v.x*sqrt(3.)*.5+v.z*.5,v.z)-i.x);" "}" - "vec2 t(vec2 v,vec2 i)" - "{" - "return v.x1e2)" + "if(i>4e2)" "break;" - "if(d.x<.001*c)" + "if(d.x<.001*i)" "{" - "n=1.;" + "m=1.;" "break;" "}" "}" - "if(c>1e2)" - "c=0.;" - "return vec3(c,l,n);" + "return vec3(i,l,m);" "}" - "vec3 e(vec3 v)" + "float t(vec3 v,vec3 i,float f)" "{" - "vec2 i=vec2(.01,0);" - "v=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);" + "float n=1.,m=.02;" + "for(int g=0;g<6;g++)" + "{" + "if(m>f)" + "break;" + "float l=t(v+m*i).x;" + "n=min(n,l/(4.*m));" + "m+=clamp(l,.1,.8);" + "if(n<-1.)" + "break;" + "}" + "n=max(n,-1.);" + "return.25*(1.+n)*(1.+n)*(2.-n);" + "}" + "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);" "}" - "vec3 e(vec3 v,vec3 i,float c,vec3 f,vec3 n,vec3 l,float m)" + "vec3 t(vec3 v,vec3 n,vec3 i,vec3 f,float m)" "{" - "v-=f;" - "float r=length(v);" + "vec3 g=vec3(.77,.26,.73);" + "v-=n;" + "float l=length(v);" "v=normalize(v);" - "r=clamp(c-r*r/11.56,0.,1.);" - "c=max(dot(l,v),0.);" - "f=normalize(v-n);" - "n=vec3(.04);" - "v=n+(1.-n)*pow(clamp(1.-max(dot(f,v),0.),0.,1.),5.);" - "return i*c*r+i*pow(max(dot(l,f),0.),mix(128.,8.,m))*r*v;" + "float x=30./(1.+.09*l+.032*l*l),c=max(dot(f,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 e(vec3 v,vec3 f,vec3 i,float n)" + "vec3 t(vec3 v,vec3 f,vec3 i,float n)" "{" "float m=.01;" - "vec3 l=vec3(0);" + "vec3 g=vec3(0);" "if(n==0.)" - "l=vec3(.8314,.2941,.2941),m=.1;" + "g=vec3(.8314,.2941,.2941),m=.1;" "else if(n==1.)" - "l=vec3(.6196,.6118,.6118),m=.7;" + "g=vec3(.6196,.6118,.6118),m=.7;" "else if(n==2.)" - "l=vec3(.3255,.4784,.3255),m=.2;" + "g=vec3(.3255,.4784,.3255),m=.2;" "else if(n==3.)" - "l=vec3(.2471,.3059,.6314),m=1.;" + "g=vec3(.2471,.3059,.6314),m=1.;" "else if(n==4.)" - "l=vec3(.9961,1,.9922),m=.1;" + "g=vec3(.9961,1,.9922),m=.1;" "else if(n==5.)" - "l=vec3(.9961,1,.9922),m=.3;" - "vec3 r=vec3(0);" - "for(float n=0.;n<16.;n++)" - "for(float l=0.;l<16.;l++)" - "{" - "ivec2 d=textureSize(c,0);" - "vec2 y=vec2(l,n)/vec2(d);" - "vec4 s=texture(c,y);" - "vec3 k=s.xyz;" - "float x=t(clamp(int(s.w/34.*512.),0,511));" - "r+=e(vec3(k.x,k.y+x+2.,k.z),vec3(.46,.2,.94)+vec3(.66,.64,.77)*cos(6.28318*(x*1.5*vec3(.91,.62,.97)+vec3(.26,.2,.84))),clamp(x*5.,0.,1.),v,i,f,m);" - "}" - "r+=vec3(.08,.62,.75)*clamp(dot(f,normalize(vec3(0,1,-3)*vec3(0,-1,-2))),0.,1.)*.8;" - "return l*max(vec3(0),r);" + "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);" "}" - "vec3 e(vec2 i,vec3 v)" + "vec3 t(vec2 n,vec3 v)" "{" - "v=normalize(vec3(0,-1,10)-v);" - "vec3 n=normalize(cross(vec3(0,1,0),v));" - "return normalize(v+i.x*n+i.y*cross(v,n));" + "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 e(vec2 v)" + "vec3 t(vec2 v)" "{" - "vec3 n=vec3(-10,20,-20),l=e(v,n),f=vec3(0),m=vec3(0);" - "n=t(n,l,m);" + "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 v=e(m);" - "f=e(m,v,l,n.y);" + "vec3 v=x(l);" + "i=t(l,v,f,n.y);" "}" - "return f;" + "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));" "}" "void main()" "{" - "vec3 n=e(gl_FragCoord.xy*vec2(.00104166667,.00185185185)-1.);" - "v=vec4(n,1);" + "vec3 v=t(gl_FragCoord.xy*vec2(.00104166667,.00185185185)-1.);" + "f=vec4(v,1);" "}"; #endif // FRAGMENT_INL_