I need help programming the Heat Equation in REGL (WebGL Library)

107 Views Asked by At

I am new to how WEBGL works so I do not understand why the Heat Equation is not working like it is supposed to. In my fragment shader, I used a sampler 2D, prevState, and a texture coordinate, uv. With the heat equation having the formula, U(i,j) += dT*(U(i,j+1)+U(i,j-1)+U(i+1,j)+U(i-1,j)-4*U(i,j))/(dX*dX), I put that formula in my fragment shader:

float u = texture2D(prevState, uv).r;
   float lu = (texture2D(prevState, vec2(uv.x, uv.y + eps) ).r + texture2D(prevState, vec2(uv.x, uv.y - eps) ).r + texture2D(prevState, vec2(uv.x + eps, uv.y) ).r + texture2D(prevState, vec2(uv.x - eps, uv.y) ).r - 4.*u)/(eps * eps);

However, when I run the HTML + JavaScript code mentioned below, I do not get a diffusive solution over time, how the heat equation should work. Instead, the function blows up and spreads, forming a diamond shape.

function main(err, regl) {


const RAD = 2048
const h = 1/(RAD - 1);
var B = 0;
const pixels = new Float32Array(RAD * RAD * 4);
for(var i = 0; i < RAD; i++){
     for(var j = 0; j < RAD; j++){
       var x = h*(j - RAD/2),  y = h*(i - RAD/2);
       pixels[B++] = 30*Math.exp(-3000*(x*x + y*y));
       pixels[B++] = 0;
       pixels[B++] = 0;
       pixels[B++] = 0;
    }
}

const state = (Array(2)).fill().map(() =>
  regl.framebuffer({
    color: regl.texture({
      radius: RAD,
      data: pixels,
      wrap: 'repeat'
    }),
    depthStencil: false
  }))

const doHeatEq = regl({
  frag: `
  precision mediump float;
  uniform sampler2D prevState;
  varying vec2 uv;
  const float eps = 1./2047., dt = .000001;
  void main() {
    float u = texture2D(prevState, uv).r;
   float lu = (texture2D(prevState, vec2(uv.x, uv.y + eps) ).r + texture2D(prevState, vec2(uv.x, uv.y - eps) ).r + texture2D(prevState, vec2(uv.x + eps, uv.y) ).r + texture2D(prevState, vec2(uv.x - eps, uv.y) ).r - 4.*u)/(eps * eps);
   u += dt * lu;
   gl_FragColor = vec4(u, 0., 0., 0. );
  }`,

  framebuffer: ({tick}) => state[(tick + 1) % 2]
})

const colorset = regl({
  frag: `
  precision mediump float;
  uniform sampler2D prevState;
  varying vec2 uv;
  void main() {
    float val = texture2D(prevState, uv).r;
   gl_FragColor = vec4(vec3(abs(val)), 1.);
  }`,

  vert: `
  precision mediump float;
  attribute vec2 position;
  varying vec2 uv;
  void main() {
    uv = 0.5 * (position + 1.0);
    gl_Position = vec4(position, 0, 1);
  }`,

  attributes: {
    position: [ -4, -4, 4, -4, 0, 4 ]
  },

  uniforms: {
    prevState: ({tick}) => state[tick % 2]
  },

  depth: { enable: false },

  count: 3
})

regl.frame(() => {
  colorset(() => {
    regl.draw()
    doHeatEq()
  })
})
}

// initialize regl
createREGL({
   extensions: 'OES_texture_float',
  // callback when regl is initialized
  onDone: main,
});
<!DOCTYPE html>
<title>Heat Equation</title>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/regl/1.3.11/regl.min.js"></script>
  <script src="https://d3js.org/d3.v4.min.js"></script>

</body>

What am I doing wrong?

0

There are 0 best solutions below