Compare commits

..

No commits in common. 'a23167c57d38d885c8f953ec26c5eff395d07bc3' and '4b0e7a99cc1cc19a90aaee07dc9bbe21428a8a49' have entirely different histories.

  1. 106
      compare_stencils.py
  2. 56
      doc/notes.txt
  3. 1
      loader.js
  4. 11
      notes.txt
  5. 268
      src/main.c
  6. 43
      src/shaders/advect.glsl
  7. 34
      src/shaders/blit_div_fragment.glsl
  8. 14
      src/shaders/blit_div_vertex.glsl
  9. 65
      src/shaders/blit_residue_fragment.glsl
  10. 6
      src/shaders/blit_vertex.glsl
  11. 48
      src/shaders/divergence.glsl
  12. 34
      src/shaders/jacobi_step.glsl
  13. 21
      src/shaders/multigrid_correct.glsl
  14. 8
      src/shaders/multigrid_restrict_residual.glsl
  15. 22
      src/shaders/splat.glsl
  16. 27
      src/shaders/subtract_pressure.glsl

@ -1,106 +0,0 @@
from sympy import sqrt, symbols, factorial, IndexedBase, Symbol
p = IndexedBase("p")
h = Symbol("h")
def taylor(a, b, c):
n = 4
derivatives = [0] * n
steps = [0] * n
result = p
for order in range(1, n+1):
for i in range(0, 3**order):
for j in range(0, order):
derivatives[j] = int((i / (3**(order-1-j))) % 3 + 1)
step = [a, b, c][derivatives[j] - 1]
steps[j] = step
total_step = 1
symbol_name = ""
for j in range(0, order):
total_step *= (steps[j] * h)
component = derivatives[j] - 1
symbol_name += ["x", "y", "z"][component]
result += (1 / factorial(order)) * total_step * Symbol(symbol_name)
return result;
def expand_laplacian(face, corner):
# Note: Any linear combination of the face and corner coefficients will
# produce a valid discretized Laplacian, except for when normalization == 0
center = face * 4 + corner * 4
normalization = face + 2 * corner
expr = (
- center * taylor(0, 0, 0)
+ face * taylor( 1, 0, 0)
+ face * taylor(-1, 0, 0)
+ face * taylor( 0, -1, 0)
+ face * taylor( 0, 1, 0)
+ corner * taylor( 1, 1, 0)
+ corner * taylor( 1, -1, 0)
+ corner * taylor(-1, 1, 0)
+ corner * taylor(-1, -1, 0)
) / (normalization*h*h)
print("Laplacian:")
print("\tCenter: {:+d}".format(-center))
print("\tFace: {:+d}".format(face))
print("\tCorner: {:+d}".format(corner))
print("\tNormalization: {:+d}".format(normalization))
print("\tExpansion: {}".format(expr.simplify()))
print()
return expr
#a = expand_laplacian(1, 0)
#b = expand_laplacian(0, 1)
#c = expand_laplacian(1, 1)
#d = expand_laplacian(2, 1)
#e = expand_laplacian(1, 2)
expr_colocated = (
-4*taylor(0, 0, 0)
+1*taylor(-2, 0, 0)
+1*taylor(+2, 0, 0)
+1*taylor(0, -2, 0)
+1*taylor(0, +2, 0)
) / (4*h*h)
expr_wide = (
-8*taylor(0, 0, 0)
+1*taylor(-1, 0, 0)
+1*taylor(+1, 0, 0)
+1*taylor(0, -1, 0)
+1*taylor(0, +1, 0)
+1*taylor(-1,-1, 0)
+1*taylor(+1,+1, 0)
+1*taylor(+1, -1, 0)
+1*taylor(-1, +1, 0)
) / (3*h*h)
expr_vertex = (
-4*taylor(0, 0, 0)
+1*taylor(-1,-1, 0)
+1*taylor(+1,+1, 0)
+1*taylor(+1, -1, 0)
+1*taylor(-1, +1, 0)
) / (2*h*h)
expr_mac = (
-4*taylor(0, 0, 0)
+1*taylor(-1, 0, 0)
+1*taylor(+1, 0, 0)
+1*taylor(0, -1, 0)
+1*taylor(0, +1, 0)
) / (h*h)
print((expr_colocated - expr_mac).simplify())
print((expr_colocated - expr_wide).simplify())
print((expr_colocated - expr_vertex).simplify())

@ -1,56 +0,0 @@
Colocated multigrid
+---+---+---+---+---+---+---+---+---+
8 | x | x | x | x | x | x | x | x | x |
+---+---+---+---+---+---+---+---+---+
7 | 0 | | | | | | | | x |
+---+---+---+---+---+---+---+---+---+
6 | 0 | | | | | | | | x |
+---+---+---+---+---+---+---+---+---+
5 | 0 | | | | | | | | x |
+---+---+---+---+---+---+---+---+---+
4 | 0 | | | | | | | | x |
+---+---+---+---+---+---+---+---+---+
3 | 0 | | | | | | | | x |
+---+---+---+---+---+---+---+---+---+
2 | 0 | | | | | | | | x |
+---+---+---+---+---+---+---+---+---+
1 | 0 | | | | | | | | x |
+---+---+---+---+---+---+---+---+---+
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | x |
+---+---+---+---+---+---+---+---+---+
0 1 2 3 4 5 6 7 8
- Pressure is defined on all cells:
- The 0 cells are stored but not used (we return p = 0 on these cells)
- The x cells are not stored (we implicitly return p = 0 out of bounds)
- Velocity is only defined in the inner cells, we always return 0 on the borders
The Coarse grid is as follows:
+-------+-------+-------+-------+-------+
| | | | | |
| x | x | x | x | x |
| | | | | |
+-------+-------+-------+-------+-------+
| | | | | |
| 0 | | | | x |
| | | | | |
+-------+-------+-------+-------+-------+
| | | | | |
| 0 | | | | x |
| | | | | |
+-------+-------+-------+-------+-------+
| | | | | |
| 0 | | | | x |
| | | | | |
+-------+-------+-------+-------+-------+
| | | | | |
| 0 | 0 | 0 | 0 | x |
| | | | | |
+-------+-------+-------+-------+-------+
So, the size of the total grid is (2^N+1)*(2^N+1), but we store only (2^N)*(2^N), and explicitly
set the pressure to 0 on the lower and left borders.

@ -808,7 +808,6 @@ function GLBindImports(env)
env.glUniform1f = function(loc, v0) { GLctx.uniform1f(GLuniforms[loc], v0); };
env.glUniform1i = function(loc, v0) { GLctx.uniform1i(GLuniforms[loc], v0); };
env.glUniform2i = function(loc, v0, v1) { GLctx.uniform2i(GLuniforms[loc], v0, v1); };
env.glUniform2f = function(loc, v0, v1) { GLctx.uniform2f(GLuniforms[loc], v0, v1); };
env.glUniform3f = function(loc, v0, v1, v2) { GLctx.uniform3f(GLuniforms[loc], v0, v1, v2); };

@ -0,0 +1,11 @@
On macOS, homebrew version of llvm must be used instead of xcode's one:
> brew install llvm
Have to run a local http server to serve files:
> python3 -m http.server
brew llvm toolchain seems to be broken and does not find open gl header files, and trying to include them from the framework path in /applications/xcode/ etc creates a bunch of other errors, so the workaround was to download mesa openGL headers, and tweak glext.h so that it includes stdint.h instead of inttypes.h (because brew's llvm can't seem to find this one). This was annoying as fuck.
Zig cc seem to have everything needed but doesn't recognize --export-all and such, so I could'nt find a way to use it.

@ -16,8 +16,6 @@
#include"blit_vertex_shader.h"
#include"blit_fragment_shader.h"
#include"blit_div_vertex_shader.h"
#include"blit_div_fragment_shader.h"
#include"common_vertex_shader.h"
#include"advect_shader.h"
#include"divergence_shader.h"
@ -26,7 +24,6 @@
#include"multigrid_correct_shader.h"
#include"subtract_pressure_shader.h"
#include"splat_shader.h"
#include"blit_residue_fragment_shader.h"
void* memcpy(void* dst, void* src, unsigned long n)
{
@ -53,7 +50,7 @@ float fabs(float x)
return(x>0 ? x : -x);
}
#define PI 3.14159265359
#define PI 3.14159
#define EULER 2.71828
#define SQRT2 1.41421
@ -136,16 +133,6 @@ typedef struct jacobi_program
} jacobi_program;
typedef struct blit_residue_program
{
GLuint prog;
GLint pos;
GLint mvp;
GLint xTex;
GLint bTex;
} blit_residue_program;
typedef struct multigrid_restrict_residual_program
{
GLuint prog;
@ -182,7 +169,6 @@ typedef struct blit_program
GLint pos;
GLint mvp;
GLint gridSize;
GLint tex;
} blit_program;
@ -197,7 +183,6 @@ typedef struct splat_program
GLint radius;
GLint additive;
GLint blending;
GLint randomize;
} splat_program;
@ -216,8 +201,7 @@ multigrid_correct_program multigridCorrectProgram;
subtract_program subtractProgram;
splat_program splatProgram;
blit_program blitProgram;
blit_program blitDivProgram;
blit_residue_program blitResidueProgram;
frame_buffer colorBuffer;
frame_buffer velocityBuffer;
@ -318,7 +302,6 @@ 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)
@ -328,29 +311,8 @@ void init_blit(blit_program* program)
program->pos = glGetAttribLocation(program->prog, "pos");
program->mvp = glGetUniformLocation(program->prog, "mvp");
program->tex = glGetUniformLocation(program->prog, "tex");
program->gridSize = glGetUniformLocation(program->prog, "gridSize");
}
void init_blit_div(blit_program* program)
{
console_log_fmt("compiling blit div...");
program->prog = compile_shader(blit_div_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");
}
void init_blit_residue(blit_residue_program* program)
{
console_log_fmt("compiling blit residue...");
program->prog = compile_shader(blit_div_vertex_shader_src, blit_residue_fragment_shader_src);
program->pos = glGetAttribLocation(program->prog, "pos");
program->mvp = glGetUniformLocation(program->prog, "mvp");
program->xTex = glGetUniformLocation(program->prog, "xTex");
program->bTex = glGetUniformLocation(program->prog, "bTex");
}
GLuint create_texture(int width, int height, GLenum internalFormat, GLenum format, GLenum type, char* initData)
{
GLuint texture;
@ -361,6 +323,7 @@ GLuint create_texture(int width, int height, GLenum internalFormat, GLenum forma
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return(texture);
}
@ -371,6 +334,7 @@ GLuint create_fbo(GLuint texture)
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindTexture(GL_TEXTURE_2D, texture);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glClear(GL_COLOR_BUFFER_BIT);
return(fbo);
}
@ -409,7 +373,10 @@ void frame_buffer_swap(frame_buffer* buffer)
//----------------------------------------------------------------
//NOTE(martin): entry point
//----------------------------------------------------------------
/*
#define texWidth 512
#define texHeight 512
*/
#define texWidth (256)
#define texHeight (256)
@ -430,11 +397,8 @@ 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);
@ -512,7 +476,6 @@ void init_velocity_vortex()
float y = 2*i/(float)texWidth - 1;
velocityInitData[i][j][0] = sinf(2*PI*y);
velocityInitData[i][j][1] = sinf(2*PI*x);
}
}
}
@ -527,27 +490,22 @@ int init(float canvasSize)
WAJS_SetupCanvas(canvasSize, canvasSize);
// init_color_checker();
// init_velocity_vortex();
// init programs
init_advect(&advectProgram);
init_div(&divProgram);
init_jacobi(&jacobiProgram);
init_multigrid_restrict_residual(&multigridRestrictResidualProgram);
init_multigrid_correct(&multigridCorrectProgram);
init_blit_residue(&blitResidueProgram);
init_subtract(&subtractProgram);
init_splat(&splatProgram);
init_blit(&blitProgram);
init_blit_div(&blitDivProgram);
// init frame buffers
console_log_fmt("create color buffer");
init_frame_buffer(&colorBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, (char*)colorInitData);
init_frame_buffer(&colorBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, 0);
console_log_fmt("create velocity buffer");
init_frame_buffer(&velocityBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, (char*)velocityInitData);
init_frame_buffer(&velocityBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, 0);
int gridFactor = 1;
for(int i=0; i<MULTIGRID_COUNT; i++)
@ -589,19 +547,10 @@ int init(float canvasSize)
return(0);
}
void apply_splat(float splatPosX, float splatPosY, float radius, float splatVelX, float splatVelY, float r, float g, float b, bool randomize)
void apply_splat(float splatPosX, float splatPosY, float splatVelX, float splatVelY, float r, float g, float b)
{
glUseProgram(splatProgram.prog);
if(randomize)
{
glUniform1f(splatProgram.randomize, 1.);
}
else
{
glUniform1f(splatProgram.randomize, 0.);
}
// force
glBindFramebuffer(GL_FRAMEBUFFER, velocityBuffer.fbos[1]);
@ -614,7 +563,7 @@ void apply_splat(float splatPosX, float splatPosY, float radius, float splatVelX
glUniform1f(splatProgram.additive, 1);
glUniform1f(splatProgram.blending, 0);
glUniform1f(splatProgram.radius, radius);
glUniform1f(splatProgram.radius, 0.01);
glDrawArrays(GL_TRIANGLES, 0, 6);
@ -631,7 +580,7 @@ void apply_splat(float splatPosX, float splatPosY, float radius, float splatVelX
glUniform3f(splatProgram.splatColor, r, g, b);
glUniform1f(splatProgram.additive, 0);
glUniform1f(splatProgram.blending, 1);
glUniform1f(splatProgram.radius, radius);
glUniform1f(splatProgram.radius, 0.01);
glDrawArrays(GL_TRIANGLES, 0, 6);
@ -639,7 +588,7 @@ void apply_splat(float splatPosX, float splatPosY, float radius, float splatVelX
}
void jacobi_solve(frame_buffer* x, frame_buffer* b, float invGridSize, int iterationCount)
void multigrid_smooth(frame_buffer* x, frame_buffer* b, float invGridSize, int iterationCount)
{
glUseProgram(jacobiProgram.prog);
@ -707,40 +656,6 @@ void multigrid_clear(frame_buffer* error)
glClear(GL_COLOR_BUFFER_BIT);
}
void input_splat(float t)
{
//NOTE: apply force and dye
if(mouseInput.down && (mouseInput.deltaX || mouseInput.deltaY))
{
// account for margin
float margin = 32;
float canvasWidth = canvas_width();
float canvasHeight = canvas_height();
float offset = margin/texWidth;
float ratio = 1 - 2*margin/texWidth;
float splatPosX = (mouseInput.x/canvasWidth)*ratio + offset;
float splatPosY = (1 - mouseInput.y/canvasHeight)*ratio + offset;
float splatVelX = (10000.*DELTA*mouseInput.deltaX/canvasWidth)*ratio;
float splatVelY = (-10000.*DELTA*mouseInput.deltaY/canvasWidth)*ratio;
float intensity = 100*sqrtf(square(ratio*mouseInput.deltaX/canvasWidth) + square(ratio*mouseInput.deltaY/canvasHeight));
float r = intensity * (sinf(2*PI*0.1*t) + 1);
float g = 0.5*intensity * (cosf(2*PI*0.1/EULER*t + 654) + 1);
float b = intensity * (sinf(2*PI*0.1/SQRT2*t + 937) + 1);
float radius = 0.005;
apply_splat(splatPosX, splatPosY, radius, splatVelX, splatVelY, r, g, b, false);
mouseInput.deltaX = 0;
mouseInput.deltaY = 0;
}
}
// This function is called by loader.js every frame
void WAFNDraw()
{
@ -771,60 +686,39 @@ void WAFNDraw()
frame_buffer_swap(&velocityBuffer);
/*
//DEBUG
static bool splatTrig = false;
static bool splat = false;
static float splatStart = 0;
static int splatDir = 0;
//NOTE: apply force and dye
if(mouseInput.down && (mouseInput.deltaX || mouseInput.deltaY))
{
float canvasWidth = canvas_width();
float canvasHeight = canvas_height();
static int frameCount = 0;
float splatPosX = mouseInput.x/canvasWidth;
float splatPosY = 1 - mouseInput.y/canvasHeight;
if(resetCmd)
{
frameCount = 0;
splat = true;
splatStart = frameT;
}
float splatVelX = 10000.*DELTA*mouseInput.deltaX/canvasWidth;
float splatVelY = -10000.*DELTA*mouseInput.deltaY/canvasWidth;
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);
float intensity = 100*sqrtf(square(mouseInput.deltaX/canvasWidth) + square(mouseInput.deltaY/canvasHeight));
float r = intensity * (sinf(2*PI*0.1*t) + 1);
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);
mouseInput.deltaX = 0;
mouseInput.deltaY = 0;
}
resetCmd = false;
if(frameCount>20)
//DEBUG
//*
if((int)(frameT*3/2.) % 6 == 0)
{
return;
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);
}
frameCount++;
*/
input_splat(t);
//*/
//NOTE: compute divergence of advected velocity
glUseProgram(divProgram.prog);
@ -839,37 +733,48 @@ void WAFNDraw()
frame_buffer_swap(&divBuffer[0]);
//NOTE: compute pressure
glBindFramebuffer(GL_FRAMEBUFFER, pressureBuffer[0].fbos[1]);
glClear(GL_COLOR_BUFFER_BIT);
#if 0
multigrid_clear(&pressureBuffer[0]);
jacobi_solve(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, texWidth*texHeight);
multigrid_smooth(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 500);
#else
//*
multigrid_clear(&pressureBuffer[0]);
for(int i=0; i<1; i++)
for(int i=0; i<4; i++)
{
jacobi_solve(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 2);
multigrid_smooth(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 2);
//*
multigrid_coarsen_residual(&divBuffer[1], &pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE);
multigrid_clear(&pressureBuffer[1]);
jacobi_solve(&pressureBuffer[1], &divBuffer[1], 2*INV_GRID_SIZE, 2);
multigrid_smooth(&pressureBuffer[1], &divBuffer[1], 2*INV_GRID_SIZE, 2);
multigrid_coarsen_residual(&divBuffer[2], &pressureBuffer[1], &divBuffer[1], 2*INV_GRID_SIZE);
multigrid_clear(&pressureBuffer[2]);
jacobi_solve(&pressureBuffer[2], &divBuffer[2], 4*INV_GRID_SIZE, 30);
multigrid_smooth(&pressureBuffer[2], &divBuffer[2], 4*INV_GRID_SIZE, 60);
multigrid_prolongate_and_correct(&pressureBuffer[1], &pressureBuffer[2], 2*INV_GRID_SIZE);
jacobi_solve(&pressureBuffer[1], &divBuffer[1], 2*INV_GRID_SIZE, 8);
multigrid_smooth(&pressureBuffer[1], &divBuffer[1], 2*INV_GRID_SIZE, 8);
multigrid_prolongate_and_correct(&pressureBuffer[0], &pressureBuffer[1], INV_GRID_SIZE);
jacobi_solve(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 4);
//*/
multigrid_smooth(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 4);
}
#endif
/*/
multigrid_clear(&pressureBuffer[0]);
multigrid_smooth(&pressureBuffer[0], &pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 10);
multigrid_coarsen_residual(&divBuffer[1], &pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE);
multigrid_clear(&pressureBuffer[1]);
multigrid_smooth(&pressureBuffer[1], &pressureBuffer[1], &divBuffer[1], 2*INV_GRID_SIZE, 400);
multigrid_prolongate_and_correct(&pressureBuffer[0], &pressureBuffer[0], &pressureBuffer[1], INV_GRID_SIZE);
multigrid_smooth(&pressureBuffer[0], &pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 10);
//*/
#endif
//NOTE: subtract pressure gradient to advected velocity
glUseProgram(subtractProgram.prog);
@ -903,40 +808,23 @@ void WAFNDraw()
glUniform1f(advectProgram.delta, DELTA);
glUniform1f(advectProgram.dissipation, 0.001);
glUniform1f(advectProgram.dissipation, 0.5);
glDrawArrays(GL_TRIANGLES, 0, 6);
frame_buffer_swap(&colorBuffer);
//*
//NOTE: Blit color texture to screen
//NOTE: blit residue to screen
glViewport(0, 0, canvas_width(), canvas_height());
float displayMatrix[16] = {
1/aspectRatio, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 };
/*
glUseProgram(blitResidueProgram.prog);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, pressureBuffer[0].textures[0]);
glUniform1i(blitResidueProgram.xTex, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, divBuffer[0].textures[0]);
glUniform1i(blitResidueProgram.bTex, 1);
glUniformMatrix4fv(blitResidueProgram.mvp, 1, GL_FALSE, displayMatrix);
glViewport(0, 0, canvas_width(), canvas_height());
glDrawArrays(GL_TRIANGLES, 0, 6);
//*/
//*
glUseProgram(blitProgram.prog);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -944,37 +832,21 @@ void WAFNDraw()
glBindTexture(GL_TEXTURE_2D, colorBuffer.textures[0]);
glUniform1i(blitProgram.tex, 0);
glUniform2i(blitProgram.gridSize, texWidth, texHeight);
glUniformMatrix4fv(blitProgram.mvp, 1, GL_FALSE, displayMatrix);
glDrawArrays(GL_TRIANGLES, 0, 6);
/*/
//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(divProgram.src, 0);
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);
//NOTE: Blit velocity to screen
glViewport(0, 0, window_width(), window_height());
glUseProgram(blitProgram.prog);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, divBuffer[0].textures[0]);
glUniform1i(blitDivProgram.tex, 0);
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
glUniform1i(blitProgram.tex, 0);
glUniformMatrix4fv(blitDivProgram.mvp, 1, GL_FALSE, displayMatrix);
glUniformMatrix4fv(blitProgram.mvp, 1, GL_FALSE, displayMatrix);
glDrawArrays(GL_TRIANGLES, 0, 6);
//*/
}

@ -11,46 +11,9 @@ uniform sampler2D velocity;
uniform float delta;
uniform float dissipation;
vec2 u(ivec2 coord)
{
return(texelFetch(velocity, coord, 0).xy);
}
vec4 q(ivec2 coord)
{
if( coord.x < 0
|| coord.x >= textureSize(src, 0).x
|| coord.y < 0
|| coord.y >= textureSize(src, 0).y)
{
return(vec4(0.));
}
return(texelFetch(src, coord, 0));
}
vec4 bilerpSrc(vec2 pos)
{
vec2 offset = fract(pos);
ivec2 bl = ivec2(floor(pos));
ivec2 br = bl + ivec2(1, 0);
ivec2 tl = bl + ivec2(0, 1);
ivec2 tr = bl + ivec2(1, 1);
vec4 lerpTop = (1.-offset.x)*q(tl) + offset.x*q(tr);
vec4 lerpBottom = (1.-offset.x)*q(bl) + offset.x*q(br);
vec4 result = (1.-offset.y)*lerpBottom + offset.y*lerpTop;
return(result);
}
void main()
{
float texWidth = float(textureSize(velocity, 0).x);
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
vec2 samplePos = vec2(pixelCoord) - texWidth * delta * u(pixelCoord);
fragColor = bilerpSrc(samplePos) / (1. + dissipation*delta);
vec2 u = texture(velocity, texCoord).xy;
vec2 samplePos = texCoord - delta * u;
fragColor = texture(src, samplePos) / (1. + dissipation*delta);
}

@ -1,34 +0,0 @@
#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(0.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()
{
ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(tex, 0).xy)));
float f = texelFetch(tex, pixelCoord, 0).x;
fragColor = vec4(color_map(f), 1.0);
}

@ -1,14 +0,0 @@
#version 300 es
precision highp float;
in vec2 pos;
out vec2 texCoord;
uniform mat4 mvp;
void main()
{
texCoord = 0.5*(pos + vec2(1,1));
gl_Position = mvp * vec4(pos, 0, 1);
}

@ -1,65 +0,0 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D xTex;
uniform sampler2D bTex;
float x(ivec2 coord)
{
if( coord.x <= 0
|| coord.x >= textureSize(xTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(xTex, 0).y)
{
return(0.);
}
return(texelFetch(xTex, coord, 0).x);
}
float b(ivec2 coord)
{
if( coord.x <= 0
|| coord.x >= textureSize(bTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(bTex, 0).y)
{
return(0.);
}
return(texelFetch(bTex, coord, 0).x);
}
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(0.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()
{
ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(xTex, 0).xy)));
float tl = x(pixelCoord + ivec2(-1, 1));
float tr = x(pixelCoord + ivec2(1, 1));
float bl = x(pixelCoord + ivec2(-1, -1));
float br = x(pixelCoord + ivec2(1, -1));
float residue = b(pixelCoord) - (-tl - tr - bl - br + 4.*x(pixelCoord));
fragColor = vec4(color_map(residue), 1);
}

@ -6,13 +6,9 @@ in vec2 pos;
out vec2 texCoord;
uniform mat4 mvp;
uniform ivec2 gridSize;
void main()
{
float margin = 32.;
float ratio = 1. - 2.*margin/float(gridSize.x);
texCoord = margin/float(gridSize.x) + ratio*(0.5*(pos + vec2(1,1)));
texCoord = 0.5*(pos + vec2(1,1));
gl_Position = mvp * vec4(pos, 0, 1);
}

@ -8,34 +8,36 @@ out vec4 fragColor;
uniform sampler2D src;
vec2 u(ivec2 coord)
float ux(ivec2 coord)
{
return(texelFetch(src, coord, 0).xy);
return(texelFetch(src, coord, 0).x);
}
float uy(ivec2 coord)
{
return(texelFetch(src, coord, 0).y);
}
void main()
{
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
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
{
vec2 tl = u(pixelCoord + ivec2(-1, 0));
vec2 tr = u(pixelCoord);
vec2 bl = u(pixelCoord + ivec2(-1, -1));
vec2 br = u(pixelCoord + ivec2(0, -1));
float r = (tr.x + br.x)/2.;
float l = (tl.x + bl.x)/2.;
float t = (tl.y + tr.y)/2.;
float b = (bl.y + br.y)/2.;
fragColor = vec4(-2.*(r - l + t - b), 0, 0, 1);
}
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);
/*
vec2 c = texelFetch(src, pixelCoord, 0).xy;
if(vr.x >= textureSize(src, 0).x) { r = -c.x; }
if(vl.x < 0) { l = -c.x; }
if(vt.y >= textureSize(src, 0).y) { t = -c.y; }
if(vb.y < 0) { b = -c.y; }
*/
fragColor = vec4(-(r - l + t - b)/2., 0, 0, 1);
}

@ -12,9 +12,9 @@ uniform sampler2D bTex;
float x(ivec2 coord)
{
if( coord.x <= 0
|| coord.x >= textureSize(xTex, 0).x
|| coord.x > textureSize(xTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(xTex, 0).y)
|| coord.y > textureSize(xTex, 0).y)
{
return(0.);
}
@ -23,13 +23,6 @@ float x(ivec2 coord)
float b(ivec2 coord)
{
if( coord.x <= 0
|| coord.x >= textureSize(bTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(bTex, 0).y)
{
return(0.);
}
return(texelFetch(bTex, coord, 0).x);
}
@ -37,19 +30,14 @@ void main()
{
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
if( pixelCoord.x <= 0
|| pixelCoord.y <= 0)
{
fragColor = vec4(0, 0, 0, 1);
}
else
{
float tl = x(pixelCoord + ivec2(-1, 1));
float tr = x(pixelCoord + ivec2(1, 1));
float bl = x(pixelCoord + ivec2(-1, -1));
float br = x(pixelCoord + ivec2(1, -1));
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 jacobi = (tl + tr + bl + br + b(pixelCoord))/4.;
fragColor = vec4(jacobi, 0, 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);
fragColor = vec4(weightedJacobi, 0, 0, 1);
}

@ -12,28 +12,9 @@ uniform float invGridSize;
float e(ivec2 coord)
{
if( coord.x <= 0
|| coord.x >= textureSize(error, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(error, 0).y)
{
return(0.);
}
return(texelFetch(error, coord, 0).x);
}
float p(ivec2 coord)
{
if( coord.x <= 0
|| coord.x >= textureSize(src, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(src, 0).y)
{
return(0.);
}
return(texelFetch(src, coord, 0).x);
}
void main()
{
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
@ -49,5 +30,5 @@ void main()
float bottomLerp = (1.-offset.x)*e(bl) + offset.x*e(br);
float bilerpError = (1.-offset.y)*bottomLerp + offset.y*topLerp;
fragColor = vec4(p(pixelCoord) + bilerpError, 0, 0, 1);
fragColor = vec4(texture(src, texCoord).x + bilerpError, 0, 0, 1);
}

@ -12,9 +12,9 @@ uniform sampler2D bTex;
float x(ivec2 coord)
{
if( coord.x <= 0
|| coord.x >= textureSize(xTex, 0).x
|| coord.x > textureSize(xTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(xTex, 0).y)
|| coord.y > textureSize(xTex, 0).y)
{
return(0.);
}
@ -24,9 +24,9 @@ float x(ivec2 coord)
float b(ivec2 coord)
{
if( coord.x <= 0
|| coord.x >= textureSize(bTex, 0).x
|| coord.x > textureSize(bTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(bTex, 0).y)
|| coord.y > textureSize(bTex, 0).y)
{
return(0.);
}

@ -13,16 +13,32 @@ 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));
{
vec2 u = force/length(force);
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*splatColor.xyz;
vec3 uAdd = u + intensity*vec3(force, 0);
vec3 uBlend = u*(1.-intensity) + intensity * splatColor;
fragColor = vec4(uAdd*additive + uBlend*blending, 1);

@ -17,13 +17,11 @@ vec2 u(ivec2 coord)
float p(ivec2 coord)
{
if( coord.x <= 0
|| coord.x >= textureSize(pressure, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(pressure, 0).y)
{
return(0.);
}
if(coord.x < 0) { coord.x = 0; }
if(coord.x >= textureSize(pressure, 0).x) { coord.x = textureSize(pressure, 0).x-1; }
if(coord.y < 0) { coord.y = 0; }
if(coord.y >= textureSize(pressure, 0).y) { coord.y = textureSize(pressure, 0).y-1; }
return(texelFetch(pressure, coord, 0).x);
}
@ -31,17 +29,12 @@ void main()
{
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
float tl = p(pixelCoord + ivec2(0, 1));
float tr = p(pixelCoord + ivec2(1, 1));
float bl = p(pixelCoord);
float br = p(pixelCoord + ivec2(1, 0));
float r = (tr + br)/2.;
float l = (tl + bl)/2.;
float t = (tl + tr)/2.;
float b = (bl + br)/2.;
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(r - l, t - b);
vec2 gradP = vec2(p(vr) - p(vl), p(vt) - p(vb))/2.;
fragColor = vec4(u(pixelCoord) - gradP, 0, 1);
}

Loading…
Cancel
Save