diff --git a/src/main.c b/src/main.c index f56bb17..314e0f7 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,7 @@ #include"blit_vertex_shader.h" #include"blit_fragment_shader.h" +#include"blit_div_fragment_shader.h" #include"common_vertex_shader.h" #include"advect_shader.h" #include"divergence_shader.h" @@ -183,6 +184,7 @@ typedef struct splat_program GLint radius; GLint additive; GLint blending; + GLint randomize; } splat_program; @@ -201,7 +203,7 @@ multigrid_correct_program multigridCorrectProgram; subtract_program subtractProgram; splat_program splatProgram; blit_program blitProgram; - +blit_program blitDivProgram; frame_buffer colorBuffer; frame_buffer velocityBuffer; @@ -302,6 +304,7 @@ void init_splat(splat_program* program) program->radius = glGetUniformLocation(program->prog, "radius"); program->additive = glGetUniformLocation(program->prog, "additive"); program->blending = glGetUniformLocation(program->prog, "blending"); + program->randomize = glGetUniformLocation(program->prog, "randomize"); } void init_blit(blit_program* program) @@ -313,6 +316,16 @@ void init_blit(blit_program* program) program->tex = glGetUniformLocation(program->prog, "tex"); } +void init_blit_div(blit_program* program) +{ + console_log_fmt("compiling blit div..."); + program->prog = compile_shader(blit_vertex_shader_src, blit_div_fragment_shader_src); + program->pos = glGetAttribLocation(program->prog, "pos"); + program->mvp = glGetUniformLocation(program->prog, "mvp"); + program->tex = glGetUniformLocation(program->prog, "tex"); +} + + GLuint create_texture(int width, int height, GLenum internalFormat, GLenum format, GLenum type, char* initData) { GLuint texture; @@ -396,8 +409,11 @@ void reset_texture(GLuint texture, float width, float height, char* initData) glTexImage2D(GL_TEXTURE_2D, 0, TEX_INTERNAL_FORMAT, width, height, 0, TEX_FORMAT, TEX_TYPE, initData); } +static bool resetCmd = false; + void reset() { + resetCmd = true; console_log_fmt("reset"); reset_texture(colorBuffer.textures[0], texWidth, texHeight, (char*)colorInitData); @@ -499,6 +515,7 @@ int init(float canvasSize) init_subtract(&subtractProgram); init_splat(&splatProgram); init_blit(&blitProgram); + init_blit_div(&blitDivProgram); // init frame buffers console_log_fmt("create color buffer"); @@ -546,10 +563,19 @@ int init(float canvasSize) return(0); } -void apply_splat(float splatPosX, float splatPosY, float splatVelX, float splatVelY, float r, float g, float b) +void apply_splat(float splatPosX, float splatPosY, float splatVelX, float splatVelY, float r, float g, float b, bool randomize) { glUseProgram(splatProgram.prog); + if(randomize) + { + glUniform1f(splatProgram.randomize, 1.); + } + else + { + glUniform1f(splatProgram.randomize, 0.); + } + // force glBindFramebuffer(GL_FRAMEBUFFER, velocityBuffer.fbos[1]); @@ -686,6 +712,7 @@ void WAFNDraw() frame_buffer_swap(&velocityBuffer); //NOTE: apply force and dye + /* if(mouseInput.down && (mouseInput.deltaX || mouseInput.deltaY)) { float canvasWidth = canvas_width(); @@ -703,21 +730,61 @@ void WAFNDraw() float g = intensity * (cosf(2*PI*0.1/EULER*t + 654) + 1); float b = intensity * (sinf(2*PI*0.1/SQRT2*t + 937) + 1); - apply_splat(splatPosX, splatPosY, splatVelX, splatVelY, r, g, b); + apply_splat(splatPosX, splatPosY, splatVelX, splatVelY, r, g, b, true); mouseInput.deltaX = 0; mouseInput.deltaY = 0; } - + */ //DEBUG - //* + /* if((int)(frameT*3/2.) % 9 == 0) { float dirX = 0.2*cosf(2*3.141516*frameT*7.26); float dirY = 0.3+0.1*sinf(frameT); - apply_splat(0.5, 0.1, dirX, dirY, 1.5, 1., 0.1); + apply_splat(0.5, 0., dirX, dirY, 1.5, 1., 0.1); } //*/ + static bool splatTrig = false; + static bool splat = false; + static float splatStart = 0; + static int splatDir = 0; + + if(resetCmd) + { + splat = true; + splatStart = frameT; + } + + if(splat) + { + if(frameT - splatStart >= 0.5) + { + splat = false; + splatDir++; + splatDir = splatDir % 3; + } + float dirX = 0; + float dirY = 0; + if(splatDir == 0) + { + dirX = 0; + dirY = 0.3; + } + if(splatDir == 1) + { + dirX = 0.3; + dirY = 0; + } + if(splatDir == 2) + { + dirX = 0.2121; + dirY = 0.2121; + } + apply_splat(0.5, 0.5, dirX, dirY, 1.5, 1., 0.1, false); + } + + resetCmd = false; //NOTE: compute divergence of advected velocity glUseProgram(divProgram.prog); @@ -733,9 +800,9 @@ void WAFNDraw() //NOTE: compute pressure - #if 0 + #if 1 multigrid_clear(&pressureBuffer[0]); - multigrid_smooth(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 500); + multigrid_smooth(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 2000); #else //* multigrid_clear(&pressureBuffer[0]); @@ -807,13 +874,12 @@ void WAFNDraw() glUniform1f(advectProgram.delta, DELTA); - glUniform1f(advectProgram.dissipation, 0.5); + glUniform1f(advectProgram.dissipation, 0.3); glDrawArrays(GL_TRIANGLES, 0, 6); frame_buffer_swap(&colorBuffer); -//* //NOTE: Blit color texture to screen float displayMatrix[16] = { @@ -822,6 +888,7 @@ void WAFNDraw() 0, 0, 1, 0, 0, 0, 0, 1 }; +/* glViewport(0, 0, canvas_width(), canvas_height()); glUseProgram(blitProgram.prog); @@ -835,16 +902,30 @@ void WAFNDraw() glDrawArrays(GL_TRIANGLES, 0, 6); /*/ - //NOTE: Blit velocity to screen - glViewport(0, 0, window_width(), window_height()); - glUseProgram(blitProgram.prog); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + + //NOTE: recompute divergence of (corrected) velocity + glUseProgram(divProgram.prog); + glBindFramebuffer(GL_FRAMEBUFFER, divBuffer[0].fbos[1]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]); - glUniform1i(blitProgram.tex, 0); + glUniform1i(divProgram.src, 0); - glUniformMatrix4fv(blitProgram.mvp, 1, GL_FALSE, displayMatrix); + glDrawArrays(GL_TRIANGLES, 0, 6); + + frame_buffer_swap(&divBuffer[0]); + + + //NOTE: Blit divergence to screen + glViewport(0, 0, canvas_width(), canvas_height()); + glUseProgram(blitDivProgram.prog); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, divBuffer[0].textures[0]); + glUniform1i(blitDivProgram.tex, 0); + + glUniformMatrix4fv(blitDivProgram.mvp, 1, GL_FALSE, displayMatrix); glDrawArrays(GL_TRIANGLES, 0, 6); //*/ diff --git a/src/shaders/blit_div_fragment.glsl b/src/shaders/blit_div_fragment.glsl new file mode 100644 index 0000000..1166e2e --- /dev/null +++ b/src/shaders/blit_div_fragment.glsl @@ -0,0 +1,33 @@ +#version 300 es + +precision highp float; +precision highp sampler2D; + +in vec2 texCoord; +out vec4 fragColor; + +uniform sampler2D tex; + +vec3 color_map(float v) +{ + float logv = log(abs(v))/log(10.0); + float f = floor(logv + 7.0); + float i = floor(4.0*(logv + 7.0 - f)); + + if(f < 0.0) return vec3(0.0); + if(f < 1.0) return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i/4.0); + if(f < 2.0) return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i/4.0); + if(f < 3.0) return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i/4.0); + if(f < 4.0) return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i/4.0); + if(f < 5.0) return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i/4.0); + if(f < 6.0) return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i/4.0); + if(f < 7.0) return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i/4.0); + if(f < 8.0) return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i/4.0); + return vec3(1.0); +} + +void main() +{ + float f = texture(tex, texCoord).x; + fragColor = vec4(color_map(f), 1.0); +} diff --git a/src/shaders/divergence.glsl b/src/shaders/divergence.glsl index 4cfca42..bf085bd 100644 --- a/src/shaders/divergence.glsl +++ b/src/shaders/divergence.glsl @@ -36,15 +36,25 @@ void main() { ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy)); - ivec2 vr = pixelCoord + ivec2(1, 0); - ivec2 vl = pixelCoord - ivec2(1, 0); - ivec2 vt = pixelCoord + ivec2(0, 1); - ivec2 vb = pixelCoord - ivec2(0, 1); + if( pixelCoord.x <= 0 + || pixelCoord.x >= textureSize(src, 0).x + || pixelCoord.y <= 0 + || pixelCoord.y >= textureSize(src, 0).y) + { + fragColor = vec4(0, 0, 0, 1); + } + else + { + ivec2 vr = pixelCoord + ivec2(1, 0); + ivec2 vl = pixelCoord - ivec2(1, 0); + ivec2 vt = pixelCoord + ivec2(0, 1); + ivec2 vb = pixelCoord - ivec2(0, 1); - float r = ux(vr); - float l = ux(vl); - float t = uy(vt); - float b = uy(vb); + float r = ux(vr); + float l = ux(vl); + float t = uy(vt); + float b = uy(vb); - fragColor = vec4(-(r - l + t - b)/2., 0, 0, 1); + fragColor = vec4(-(r - l + t - b)/2., 0, 0, 1); + } } diff --git a/src/shaders/jacobi_step.glsl b/src/shaders/jacobi_step.glsl index 7d7bc67..6493091 100644 --- a/src/shaders/jacobi_step.glsl +++ b/src/shaders/jacobi_step.glsl @@ -37,14 +37,24 @@ void main() { ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy)); - ivec2 vr = pixelCoord + ivec2(1, 0); - ivec2 vl = pixelCoord - ivec2(1, 0); - ivec2 vt = pixelCoord + ivec2(0, 1); - ivec2 vb = pixelCoord - ivec2(0, 1); + if( pixelCoord.x <= 0 + || pixelCoord.x >= textureSize(xTex, 0).x + || pixelCoord.y <= 0 + || pixelCoord.y >= textureSize(xTex, 0).y) + { + fragColor = vec4(0, 0, 0, 1); + } + else + { + ivec2 vr = pixelCoord + ivec2(1, 0); + ivec2 vl = pixelCoord - ivec2(1, 0); + ivec2 vt = pixelCoord + ivec2(0, 1); + ivec2 vb = pixelCoord - ivec2(0, 1); - float w = 0.8; - float standardJacobi = (x(vl) + x(vr) + x(vt) + x(vb) + b(pixelCoord))/4.; - float weightedJacobi = w*standardJacobi + (1.-w)*x(pixelCoord); + float w = 0.8; + float standardJacobi = (x(vl) + x(vr) + x(vt) + x(vb) + b(pixelCoord))/4.; + float weightedJacobi = w*standardJacobi + (1.-w)*x(pixelCoord); - fragColor = vec4(weightedJacobi, 0, 0, 1); + fragColor = vec4(weightedJacobi, 0, 0, 1); + } } diff --git a/src/shaders/splat.glsl b/src/shaders/splat.glsl index 3fb1046..ae76b3c 100644 --- a/src/shaders/splat.glsl +++ b/src/shaders/splat.glsl @@ -13,30 +13,35 @@ uniform float radius; uniform float additive; uniform float blending; +uniform float randomize; + void main() { float d2 = dot(texCoord - splatPos, texCoord - splatPos); float intensity = exp(-10.*d2/radius); - - float n = 119.*gl_FragCoord.x + 107.*gl_FragCoord.y + 113.; - n = fract(n*fract(n/2.7182818)); - intensity += intensity*abs(cos(2.*3.14159*n)); - - //NOTE: the force is added in the additive part. vec2 force = splatColor.xy; - force.x += 0.2*sin(2.*3.14159*fract(n/1.144213)); - force.y += 0.2*cos(2.*3.14159*fract(n/1.144213)); + if(randomize != 0.0) { - vec2 u = force/length(force); + float n = 119.*gl_FragCoord.x + 107.*gl_FragCoord.y + 113.; + n = fract(n*fract(n/2.7182818)); + intensity += intensity*abs(cos(2.*3.14159*n)); + + //NOTE: the force is added in the additive part. + + force.x += 0.2*sin(2.*3.14159*fract(n/1.144213)); + force.y += 0.2*cos(2.*3.14159*fract(n/1.144213)); - vec2 v = texCoord - splatPos; - vec2 norm = v - dot(v, u)*u; - float dFromAxis = length(norm); + { + vec2 u = force/length(force); - force += 30.*norm; - } + vec2 v = texCoord - splatPos; + vec2 norm = v - dot(v, u)*u; + float dFromAxis = length(norm); + force += 30.*norm; + } + } vec3 u = texture(src, texCoord).xyz; vec3 uAdd = u + intensity*vec3(force, 0); vec3 uBlend = u*(1.-intensity) + intensity * splatColor; diff --git a/src/shaders/subtract_pressure.glsl b/src/shaders/subtract_pressure.glsl index eec427f..7e6827d 100644 --- a/src/shaders/subtract_pressure.glsl +++ b/src/shaders/subtract_pressure.glsl @@ -38,12 +38,22 @@ void main() { ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy)); - ivec2 vr = pixelCoord + ivec2(1, 0); - ivec2 vl = pixelCoord - ivec2(1, 0); - ivec2 vt = pixelCoord + ivec2(0, 1); - ivec2 vb = pixelCoord - ivec2(0, 1); + if( pixelCoord.x <= 0 + || pixelCoord.x >= textureSize(src, 0).x + || pixelCoord.y <= 0 + || pixelCoord.y >= textureSize(src, 0).y) + { + fragColor = vec4(0, 0, 0, 1); + } + else + { + ivec2 vr = pixelCoord + ivec2(1, 0); + ivec2 vl = pixelCoord - ivec2(1, 0); + ivec2 vt = pixelCoord + ivec2(0, 1); + ivec2 vb = pixelCoord - ivec2(0, 1); - vec2 gradP = vec2(p(vr) - p(vl), p(vt) - p(vb))/2.; + vec2 gradP = vec2(p(vr) - p(vl), p(vt) - p(vb))/2.; - fragColor = vec4(u(pixelCoord) - gradP, 0, 1); + fragColor = vec4(u(pixelCoord) - gradP, 0, 1); + } }