diff --git a/index.html b/index.html
index 6220badfd7cf11ec71c21e5713a720e45cd3acab..567fe1e9cb09db47ca83a4772a89e54023a27f52 100644
--- a/index.html
+++ b/index.html
@@ -29,6 +29,31 @@
         }
     </script>
 
+    <script id="gradientSubtractionShader" type="x-shader/x-fragment">
+        precision mediump float;
+
+        uniform sampler2D u_velocity;
+        uniform sampler2D u_pressure;
+
+        uniform vec2 u_textureSize;
+
+        uniform float u_const;
+
+        void main() {
+
+            vec2 fragCoord = gl_FragCoord.xy;
+
+            vec2 currentVelocity = texture2D(u_velocity, fragCoord/u_textureSize).xy;
+
+            float n = texture2D(u_pressure, (fragCoord+vec2(0.0, 1.0))/u_textureSize).x;
+            float s = texture2D(u_pressure, (fragCoord+vec2(0.0, -1.0))/u_textureSize).x;
+            float e = texture2D(u_pressure, (fragCoord+vec2(1.0, 0.0))/u_textureSize).x;
+            float w = texture2D(u_pressure, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).x;
+
+            gl_FragColor = vec4(currentVelocity-u_const*vec2(e-w, n-s), 0, 0);
+        }
+    </script>
+
     <script id="divergenceShader" type="x-shader/x-fragment">
         precision mediump float;
 
@@ -36,7 +61,7 @@
 
         uniform vec2 u_textureSize;
 
-        uniform float u_halfReciprocalDx;
+        uniform float u_const;
 
         void main() {
 
@@ -49,7 +74,8 @@
             float e = texture2D(u_velocity, (fragCoord+vec2(1.0, 0.0))/u_textureSize).x;
             float w = texture2D(u_velocity, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).x;
 
-            gl_FragColor = vec4(u_halfReciprocalDx*(e-w + n-s), 0, 0, 0);
+            float div = u_const*(e-w + n-s);
+            gl_FragColor = vec4(div, div, 0, 0);
         }
     </script>
 
@@ -138,11 +164,16 @@
 
             vec2 pxCenter = vec2(0.5, 0.5);
             vec2 pos = fragCoord - pxCenter - u_dt*currentVelocity;
-            if (pos.x < 0.0 || pos.x >= u_textureSize.x-1.0 || pos.y < 0.0 || pos.y >= u_textureSize.y-1.0){
-                //boundary
-                gl_FragColor = vec4(0);
-                return;
-            }
+            //if (pos.x < 0.0 || pos.x >= u_textureSize.x-1.0 || pos.y < 0.0 || pos.y >= u_textureSize.y-1.0){
+            //    //boundary
+            //    gl_FragColor = vec4(0);
+            //    return;
+            //}
+            //periodic boundary
+            if (pos.x < 0.0) pos.x += u_textureSize.x-1.0;
+            if (pos.x >= u_textureSize.x-1.0) pos.x -= u_textureSize.x-1.0;
+            if (pos.y < 0.0) pos.y += u_textureSize.y-1.0;
+            if (pos.y >= u_textureSize.y-1.0) pos.y -= u_textureSize.y-1.0;
 
             //bilinear interp between nearest cells
             vec2 ceiled = ceil(pos);
@@ -165,46 +196,6 @@
         }
     </script>
 
-    <script id="2d-fragment-shader" type="x-shader/x-fragment">
-        precision mediump float;
-        #define M_PI 3.1415926535897932384626433832795
-
-        //texture array
-        uniform sampler2D u_image;//u, v, --, -- = r, g, b, a
-
-        uniform vec2 u_textureSize;
-
-        uniform vec2 u_mouseCoord;
-        uniform float u_mouseEnable;
-
-	    const float dt = 1.0;
-
-        void main() {
-
-            vec2 fragCoord = gl_FragCoord.xy;
-
-            vec2 currentState = texture2D(u_image, fragCoord/u_textureSize).xy;
-            float u = currentState.x;
-            float v = currentState.y;
-
-            vec2 n = texture2D(u_image, (fragCoord + vec2(0.0, 1.0))/u_textureSize).xy;//north
-            vec2 s = texture2D(u_image, (fragCoord + vec2(0.0, -1.0))/u_textureSize).xy;//south
-            vec2 e = texture2D(u_image, (fragCoord + vec2(-1.0, 0.0))/u_textureSize).xy;//east
-            vec2 w = texture2D(u_image, (fragCoord + vec2(1.0, 0.0))/u_textureSize).xy;//west
-
-            if (u_mouseEnable == 1.0){
-                vec2 pxDistFromMouse = (fragCoord - u_mouseCoord)*(fragCoord - u_mouseCoord);
-                float tol = 10.0;
-                if (length(pxDistFromMouse)<tol){
-                    gl_FragColor = vec4(0.5, 0.35, 0, 1);
-                    return;
-                }
-            }
-
-            gl_FragColor = vec4(0,0, 0, 1);
-        }
-    </script>
-
     <script type="text/javascript" src="dependencies/jquery-3.1.0.min.js"></script>
     <script type="text/javascript" src="dependencies/flat-ui.min.js"></script>
 
diff --git a/main.js b/main.js
index f19f6102c772075980ad41c86fad344ce8762db5..c44b0f58ec35261570c5723ca8c240ac98e58c94 100755
--- a/main.js
+++ b/main.js
@@ -11,6 +11,7 @@ var paused = false;//while window is resizing
 var dt = 1;
 var dx = 1;
 var nu = 1;//viscosity
+var rho = 1;//density
 
 var GPU;
 
@@ -46,9 +47,15 @@ function initGL() {
     GPU.setUniformForProgram("advect", "u_velocity", 0, "1i");
     GPU.setUniformForProgram("advect", "u_material", 1, "1i");
 
+    GPU.createProgram("gradientSubtraction", "2d-vertex-shader", "gradientSubtractionShader");
+    GPU.setUniformForProgram("gradientSubtraction" ,"u_textureSize", [width, height], "2f");
+    GPU.setUniformForProgram("gradientSubtraction", "u_const", 0.5/dx, "1f");//dt/(2*rho*dx)
+    GPU.setUniformForProgram("gradientSubtraction", "u_velocity", 0, "1i");
+    GPU.setUniformForProgram("gradientSubtraction", "u_pressure", 1, "1i");
+
     GPU.createProgram("diverge", "2d-vertex-shader", "divergenceShader");
     GPU.setUniformForProgram("diverge" ,"u_textureSize", [width, height], "2f");
-    GPU.setUniformForProgram("diverge", "u_halfReciprocalDx", 1/(2*dx), "1f");
+    GPU.setUniformForProgram("diverge", "u_const", 0.5/dx, "1f");//-2*dx*rho/dt
     GPU.setUniformForProgram("diverge", "u_velocity", 0, "1i");
 
     GPU.createProgram("force", "2d-vertex-shader", "forceShader");
@@ -88,7 +95,11 @@ function render(){
 
         GPU.step("advect", ["velocity", "velocity"], "nextVelocity");//advect velocity
         GPU.swapTextures("velocity", "nextVelocity");
-        for (var i=0;i<1;i++){
+        GPU.setProgram("jacobi");
+        var alpha = dx*dx/(nu*dt);
+        GPU.setUniformForProgram("jacobi", "u_alpha", alpha, "1f");
+        GPU.setUniformForProgram("jacobi", "u_reciprocalBeta", 1/(4+alpha), "1f");
+        for (var i=0;i<3;i++){
             GPU.step("jacobi", ["velocity", "velocity"], "nextVelocity");//diffuse velocity
             GPU.step("jacobi", ["nextVelocity", "nextVelocity"], "velocity");//diffuse velocity
         }
@@ -104,18 +115,22 @@ function render(){
         GPU.step("force", ["velocity"], "nextVelocity");
         GPU.swapTextures("velocity", "nextVelocity");
 
-        //compute pressure
+        // compute pressure
         GPU.step("diverge", ["velocity"], "velocityDivergence");//calc velocity divergence
-        for (var i=0;i<3;i++){
+        GPU.setProgram("jacobi");
+        GPU.setUniformForProgram("jacobi", "u_alpha", -dx*dx, "1f");
+        GPU.setUniformForProgram("jacobi", "u_reciprocalBeta", 1/4, "1f");
+        for (var i=0;i<20;i++){
             GPU.step("jacobi", ["velocityDivergence", "pressure"], "nextPressure");//diffuse velocity
             GPU.step("jacobi", ["velocityDivergence", "nextPressure"], "pressure");//diffuse velocity
         }
 
-        //subtract pressure gradient
+        // subtract pressure gradient
+        GPU.step("gradientSubtraction", ["velocity", "pressure"], "nextVelocity");
+        GPU.swapTextures("velocity", "nextVelocity");
 
         // GPU.step("diffuse", ["material"], "nextMaterial");
         GPU.step("advect", ["velocity", "material"], "nextMaterial");
-        // GPU.step("force", ["material"], "nextMaterial");
         GPU.step("render", ["nextMaterial"]);
         GPU.swapTextures("nextMaterial", "material");
 
@@ -144,6 +159,13 @@ function resetWindow(){
     GPU.setSize(width, height);
 
     var velocity = new Float32Array(width*height*4);
+    // for (var i=0;i<height;i++){
+    //     for (var j=0;j<width;j++){
+    //         var index = 4*(i*width+j);
+    //         velocity[index] = Math.sin(2*Math.PI*i/200)/10;
+    //         velocity[index+1] = Math.sin(2*Math.PI*j/200)/10;
+    //     }
+    // }
     GPU.initTextureFromData("velocity", width, height, "FLOAT", velocity, true);
     GPU.initFrameBufferForTexture("velocity");
     GPU.initTextureFromData("nextVelocity", width, height, "FLOAT", new Float32Array(width*height*4), true);
@@ -160,7 +182,8 @@ function resetWindow(){
     for (var i=0;i<height;i++){
         for (var j=0;j<width;j++){
             var index = 4*(i*width+j);
-            material[index] = Math.random();
+            if (((Math.floor(i/50))%2 && (Math.floor(j/50))%2)
+                || ((Math.floor(i/50))%2 == 0 && (Math.floor(j/50))%2 == 0)) material[index] = 1.0;
         }
     }
     GPU.initTextureFromData("material", width, height, "FLOAT", material, true);