Valentine's Day Special | Love Letter In HTML, CSS | #untoldCoding

 In this blog we explain how to make Love Letter In HTML, CSS On the occasion on Valentine's Day.

Here we need 2 html file .


Valentine's Day Specia




1st we Desgin 1st page


Valentine's Day Special





Document
HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>UntoldCoding</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <section id="home" class="home">
      <div class="home_section"></div>
      <div id="container">
        <div class="left"></div>
        <div class="right"></div>
        <a href="new.html"
          ><p>
            Happy Valentine's Day <br />

            <span>Click Here</span>
          </p></a
        >
      </div>
      <h1><span>I&nbsp;</span><span>You</span></h1>
      <h2>
        I have Something for you💖 <br />
        Please Hover on Above Text And click on Valentine's Heart
      </h2>
    </section>
  </body>
</html>

Now We have to Add CSS File for this


Document
CSS
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#home {
  width: 100%;
  height: 100vh;
  background-image: url(https://i.postimg.cc/c4kmCsF1/people-2597454-640.jpg);
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  background-color: rgba(255, 255, 255, 0.16);
  background-blend-mode: overlay;
  display: flex;
  justify-content: center;
  align-items: center;
  background-attachment: fixed;

  animation-name: bg-change;
  animation-duration: 15s;
  animation-timing-function: linear;
  animation-direction: alternate;
  animation-iteration-count: infinite;

  overflow: hidden;
}

@keyframes bg-change {
  from {
    background-image: url(https://i.postimg.cc/mDfh5hKD/couple-silhouette-sunset-scenery-digital-art-4k-wallpaper-uhdpaper-com-777-0-i.jpg);
  }

  to {
    background-image: url(https://i.postimg.cc/8PLvQNxn/couple-silhouette-sunset-digital-art-4k-wallpaper-uhdpaper-com-222-0-g.jpg);
  }
}

.home_section {
  width: 80%;
  min-height: 400px;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px;
}

/**************/

#container {
  width: 30vw;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: Beat 2s ease infinite alternate;

  position: absolute;
  left: 35%;
  top: -7%;
}
#container a {
  position: absolute;
  text-decoration: none;
  color: white;
  text-align: center;
  font-weight: 700;
  font-family: cursive;
}
#container span {
  color: rgb(255, 255, 255);
  font-weight: 300;
  font-size: 10px;
  padding-top: 100px;
}
.left {
  background-color: red;
  height: 12vw;
  aspect-ratio: 1/1.5;
  border-radius: 50% 50% 0% 0%;
  rotate: -47deg;
  translate: 30%;
}
.right {
  background-color: red;
  height: 12vw;
  aspect-ratio: 1/1.5;
  border-radius: 50% 50% 0% 0%;
  rotate: 47deg;
  translate: -30%;
}
@keyframes Beat {
  0% {
    transform: scale(120%);
    filter: drop-shadow(10px 10px 6px #f00606);
  }
  40% {
    transform: scale(100%);
    filter: drop-shadow(10px 10px 60px #f00606);
  }
  100% {
    transform: scale(120%);
    filter: drop-shadow(10px 10px 90px #f00606);
  }
}

h2 {
  position: absolute;
  color: rgb(255, 255, 255);
  font-family: cursive;
  font-weight: 900;
  white-space: nowrap;
  bottom: 8%;
  text-align: center;
  animation: flicker 0.5s ease-in-out infinite alternate;
}
@keyframes flicker {
  0% {
    opacity: 0.8;
    text-shadow: 2px 2px 10px rgb(0, 0, 0);
  }
  100% {
    opacity: 1;
    text-shadow: 2px 2px 20px rgb(255, 0, 0);
  }
}

h1 {
  color: #ffffff;
  font-size: 50px;
  font-weight: bold;
  font-family: cursive;
  letter-spacing: 7px;
  cursor: pointer;
  position: absolute;
  bottom: 30%;
}
h1 span {
  transition: 0.2s linear;
}
h1:hover span:nth-child(1) {
  margin-right: 5px;
}
h1:hover span:nth-child(1):after {
  content: "💖";
}
h1:hover span:nth-child(2) {
  margin-left: 30px;
}
h1:hover span {
  color: #fff;
  text-shadow: 0 0 10px #da2626, 0 0 20px #e74343, 0 0 40px #fff;
}
@media only screen and (min-device-width: 320px) and (max-device-width: 480px) {
  h2,
  p {
    font-size: 10px;
  }
  .left {
    height: 22vw;
  }
  .right {
    height: 22vw;
  }
}
This is about 1st page

In above section where we discuss about Valentine's Day Special. We use Different Tag:

1. Html 
  • <head> : 
  1. You can use the <head> tag to link to external files such as CSS stylesheets and JavaScript scripts.
  2. These files determine how your website looks and interacts.
  3. Linking them in the <head> ensures that they load before the page content, resulting in a faster and more intuitive experience.
  • <body>
  1. <head> provides global content, <body> shows the structure and organization of your content.
  2. You can use various HTML elements in <body>, such as <div>, <span>, <section>, and <article> to organize your content into blocks, columns, and other meaningful formats.
  • <Section> 
When writing, you can use sections to organize your content into manageable chunks with clear topics. This makes your writing easier to read and understand.
  • <div> 
You can use <div> tags to group related content on your website. This could be something that:

Blogpost sections: introduction, body paragraphs, conclusion

Navigation Bar: Links to different pages on your site

Product listing on the e-commerce site: Each product displayed in a separate <div>
  • <p> 
Just wrap your text in <p> and </p> tags and display it as a paragraph. Simple and effective!

Eg. 
<p>This is a paragraph. This contains multiple lines of text.</p>
<p>Here's another paragraph, starting on a new line.</p>

  • <a>

  • <h1>
  • <h2>
  • <h3>
  • <span>
  • &nbsp;


Now We have to desgin 2nd page which contain Hidden Text Animation

Love Letter In HTML, CSS


To Create this animation 1st we need  Html File



Now we have to add CSS File For this Valentine's Day Special Effect



UntoldCoding
HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="new.css" />
  </head>
  <body>
    <div class="content">
      <img src="" alt="" />
      <div class="text">
        <p>
          Love💖,
          <br />
          I want to promise you that there will be no day of your life when you
          will not find me by your side. There will be no day when I will not be
          loving you and pampering you because you mean the world to me. You are
          my inspiration; you make me want to be the best for you because you
          are the best for me. I am so delighted and glad, and I am filled with
          joy to be called your man — in other words, I’m satisfied. I love you,
          my baby🤞. I will adore every bit of you because you deserve
          everything
        </p>
        <p>Missing You A Lot 🤞💖</p>
      </div>
    </div>
    <h3>Swipe on screen to see the Secert Message</h3>
    <canvas></canvas>

    
    <script src="untoldcodding.js"></script>
  </body>
</html>
 

Now We have to Add Css For this 
UntoldCoding
CSS
html,
body {
  overflow: hidden;
  padding: 0;
  margin: 0;
  background-color: rgba(255, 0, 0, 0.693);
}

canvas {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.content {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
}

@media (max-aspect-ratio: 3/5) {
  p {
    left: 30%;
  }
}

.overlay {
  position: fixed;
  top: 50%;
  left: 30%;
  max-width: 50%;
  transform: translate(-50%, -50%);
  font-family: sans-serif;
  font-size: 10vh;
  font-weight: bold;
  pointer-events: none;
  p-transform: uppercase;
}

@media (max-aspect-ratio: 1/1) {
  .overlay {
    left: 50%;
    width: 90%;
    max-width: 90%;
  }
}

@media (max-aspect-ratio: 3/5) {
  .overlay {
    font-size: 5vh;
  }
}

.text {
  font-size: 200%;
  margin-bottom: 10%;
  width: 60%;
  height: 80%;
  justify-content: center;
  color: white;
  margin-left: 20%;
  font-family: cursive;
  font-weight: 900;
}
h3 {
  position: absolute;
  z-index: 8;
  left: 40%;
  bottom: 5%;
}

After this we need to add JavaScript File , You have to add this file between in body tag of new file


UntoldCoding
JavaScript
<script type="x-shader/x-fragment" id="vertShader">
      precision highp float;

        attribute vec2 aPosition;
        varying vec2 vUv;
        varying vec2 vL;
        varying vec2 vR;
        varying vec2 vT;
        varying vec2 vB;
        uniform vec2 u_vertex_texel;

        void main () {
            vUv = aPosition * .5 + .5;
            vL = vUv - vec2(u_vertex_texel.x, 0.);
            vR = vUv + vec2(u_vertex_texel.x, 0.);
            vT = vUv + vec2(0., u_vertex_texel.y);
            vB = vUv - vec2(0., u_vertex_texel.y);
            gl_Position = vec4(aPosition, 0., 1.);
        }
    </script>

    <script type="x-shader/x-fragment" id="fragShaderAdvection">
      precision highp float;
        precision highp sampler2D;

        varying vec2 vUv;
        uniform sampler2D u_velocity_txr;
        uniform sampler2D u_input_txr;
        uniform vec2 u_vertex_texel;
        uniform vec2 u_output_textel;
        uniform float u_dt;
        uniform float u_dissipation;

        vec4 bilerp (sampler2D sam, vec2 uv, vec2 tsize) {
            vec2 st = uv / tsize - 0.5;

            vec2 iuv = floor(st);
            vec2 fuv = fract(st);

            vec4 a = texture2D(sam, (iuv + vec2(0.5, 0.5)) * tsize);
            vec4 b = texture2D(sam, (iuv + vec2(1.5, 0.5)) * tsize);
            vec4 c = texture2D(sam, (iuv + vec2(0.5, 1.5)) * tsize);
            vec4 d = texture2D(sam, (iuv + vec2(1.5, 1.5)) * tsize);

            return mix(mix(a, b, fuv.x), mix(c, d, fuv.x), fuv.y);
        }

        void main () {
            vec2 coord = vUv - u_dt * bilerp(u_velocity_txr, vUv, u_vertex_texel).xy * u_vertex_texel;
            gl_FragColor = u_dissipation * bilerp(u_input_txr, coord, u_output_textel);
            gl_FragColor.a = 1.;
        }
    </script>

    <script type="x-shader/x-fragment" id="fragShaderDivergence">
      precision highp float;
        precision highp sampler2D;

        varying highp vec2 vUv;
        varying highp vec2 vL;
        varying highp vec2 vR;
        varying highp vec2 vT;
        varying highp vec2 vB;
        uniform sampler2D u_velocity_txr;

        void main () {
            float L = texture2D(u_velocity_txr, vL).x;
            float R = texture2D(u_velocity_txr, vR).x;
            float T = texture2D(u_velocity_txr, vT).y;
            float B = texture2D(u_velocity_txr, vB).y;

            float div = .5 * (R - L + T - B);
            gl_FragColor = vec4(div, 0., 0., 1.);
        }
    </script>

    <script type="x-shader/x-fragment" id="fragShaderPressure">
      precision highp float;
        precision highp sampler2D;

        varying highp vec2 vUv;
        varying highp vec2 vL;
        varying highp vec2 vR;
        varying highp vec2 vT;
        varying highp vec2 vB;
        uniform sampler2D u_pressure_txr;
        uniform sampler2D u_divergence_txr;

        void main () {
            float L = texture2D(u_pressure_txr, vL).x;
            float R = texture2D(u_pressure_txr, vR).x;
            float T = texture2D(u_pressure_txr, vT).x;
            float B = texture2D(u_pressure_txr, vB).x;
            float C = texture2D(u_pressure_txr, vUv).x;
            float divergence = texture2D(u_divergence_txr, vUv).x;
            float pressure = (L + R + B + T - divergence) * 0.25;
            gl_FragColor = vec4(pressure, 0., 0., 1.);
        }
    </script>

    <script type="x-shader/x-fragment" id="fragShaderGradientSubtract">
      precision highp float;
        precision highp sampler2D;

        varying highp vec2 vUv;
        varying highp vec2 vL;
        varying highp vec2 vR;
        varying highp vec2 vT;
        varying highp vec2 vB;
        uniform sampler2D u_pressure_txr;
        uniform sampler2D u_velocity_txr;

        void main () {
            float L = texture2D(u_pressure_txr, vL).x;
            float R = texture2D(u_pressure_txr, vR).x;
            float T = texture2D(u_pressure_txr, vT).x;
            float B = texture2D(u_pressure_txr, vB).x;
            vec2 velocity = texture2D(u_velocity_txr, vUv).xy;
            velocity.xy -= vec2(R - L, T - B);
            gl_FragColor = vec4(velocity, 0., 1.);
        }
    </script>

    <script type="x-shader/x-fragment" id="fragShaderPoint">
      precision highp float;
        precision highp sampler2D;

        varying vec2 vUv;
        uniform sampler2D u_input_txr;
        uniform float u_ratio;
        uniform vec3 u_point_value;
        uniform vec2 u_point;
        uniform float u_point_size;

        void main () {
            vec2 p = vUv - u_point.xy;
            p.x *= u_ratio;
            vec3 splat = pow(2., -dot(p, p) / u_point_size) * u_point_value;
            vec3 base = texture2D(u_input_txr, vUv).xyz;
            gl_FragColor = vec4(base + splat, 1.);
        }
    </script>

    <script type="x-shader/x-fragment" id="fragShaderDisplay">
      precision highp float;
        precision highp sampler2D;

        varying vec2 vUv;
        uniform sampler2D u_output_texture;

        void main () {
            vec3 C = texture2D(u_output_texture, vUv).rgb;
            float a = max(C.r, max(C.g, C.b));
            a = pow(.1 * a, .1);
            a = clamp(a, 0., 1.);
            gl_FragColor = vec4(1. - C, 1. - a);
        }
    </script>

At Last We need One External File of JavaScript 


UntoldCoding
JavaScript
const canvas = document.getElementsByTagName("canvas")[0];
const image = document.getElementsByTagName("p")[0];
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;

const params = {
  SIM_RESOLUTION: 128,
  DYE_RESOLUTION: 1024,
  DENSITY_DISSIPATION: 0.995,
  VELOCITY_DISSIPATION: 0.9,
  PRESSURE_ITERATIONS: 10,
  SPLAT_RADIUS: 3 / window.innerHeight,
  color: { r: 0.8, g: 0.5, b: 0.2 },
};

const pointer = {
  x: 0.65 * window.innerWidth,
  y: 0.5 * window.innerHeight,
  dx: 0,
  dy: 0,
  moved: false,
  firstMove: false,
};
window.setTimeout(() => {
  pointer.firstMove = true;
}, 3000);

let prevTimestamp = Date.now();

const gl = canvas.getContext("webgl");
gl.getExtension("OES_texture_float");

let outputColor, velocity, divergence, pressure;

const vertexShader = createShader(
  document.getElementById("vertShader").innerHTML,
  gl.VERTEX_SHADER
);

const splatProgram = createProgram("fragShaderPoint");
const divergenceProgram = createProgram("fragShaderDivergence");
const pressureProgram = createProgram("fragShaderPressure");
const gradientSubtractProgram = createProgram("fragShaderGradientSubtract");
const advectionProgram = createProgram("fragShaderAdvection");
const displayProgram = createProgram("fragShaderDisplay");

initFBOs();
render();
image.style.opacity = "1";

window.addEventListener("resize", () => {
  params.SPLAT_RADIUS = 5 / window.innerHeight;
  canvas.width = canvas.clientWidth;
  canvas.height = canvas.clientHeight;
});

canvas.addEventListener("click", (e) => {
  pointer.dx = 10;
  pointer.dy = 10;
  pointer.x = e.pageX;
  pointer.y = e.pageY;
  pointer.firstMove = true;
});

canvas.addEventListener("mousemove", (e) => {
  pointer.moved = true;
  pointer.dx = 5 * (e.pageX - pointer.x);
  pointer.dy = 5 * (e.pageY - pointer.y);
  pointer.x = e.pageX;
  pointer.y = e.pageY;
  pointer.firstMove = true;
});

canvas.addEventListener("touchmove", (e) => {
  e.preventDefault();
  pointer.moved = true;
  pointer.dx = 8 * (e.targetTouches[0].pageX - pointer.x);
  pointer.dy = 8 * (e.targetTouches[0].pageY - pointer.y);
  pointer.x = e.targetTouches[0].pageX;
  pointer.y = e.targetTouches[0].pageY;
  pointer.firstMove = true;
});

function createProgram(elId) {
  const shader = createShader(
    document.getElementById(elId).innerHTML,
    gl.FRAGMENT_SHADER
  );
  const program = createShaderProgram(vertexShader, shader);
  const uniforms = getUniforms(program);
  return {
    program,
    uniforms,
  };
}

function createShaderProgram(vertexShader, fragmentShader) {
  const program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);

  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    console.error(
      "Unable to initialize the shader program: " +
        gl.getProgramInfoLog(program)
    );
    return null;
  }

  return program;
}

function getUniforms(program) {
  let uniforms = [];
  let uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
  for (let i = 0; i < uniformCount; i++) {
    let uniformName = gl.getActiveUniform(program, i).name;
    uniforms[uniformName] = gl.getUniformLocation(program, uniformName);
  }
  return uniforms;
}

function createShader(sourceCode, type) {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, sourceCode);
  gl.compileShader(shader);

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    console.error(
      "An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader)
    );
    gl.deleteShader(shader);
    return null;
  }

  return shader;
}

function blit(target) {
  gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
  gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([-1, -1, -1, 1, 1, 1, 1, -1]),
    gl.STATIC_DRAW
  );
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
  gl.bufferData(
    gl.ELEMENT_ARRAY_BUFFER,
    new Uint16Array([0, 1, 2, 0, 2, 3]),
    gl.STATIC_DRAW
  );
  gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(0);

  if (target == null) {
    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  } else {
    gl.viewport(0, 0, target.width, target.height);
    gl.bindFramebuffer(gl.FRAMEBUFFER, target.fbo);
  }
  gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
}

function initFBOs() {
  const simRes = getResolution(params.SIM_RESOLUTION);
  const dyeRes = getResolution(params.DYE_RESOLUTION);

  outputColor = createDoubleFBO(dyeRes.width, dyeRes.height);
  velocity = createDoubleFBO(simRes.width, simRes.height);
  divergence = createFBO(simRes.width, simRes.height, gl.RGB);
  pressure = createDoubleFBO(simRes.width, simRes.height, gl.RGB);
}

function getResolution(resolution) {
  let aspectRatio = gl.drawingBufferWidth / gl.drawingBufferHeight;
  if (aspectRatio < 1) aspectRatio = 1 / aspectRatio;

  let min = Math.round(resolution);
  let max = Math.round(resolution * aspectRatio);

  if (gl.drawingBufferWidth > gl.drawingBufferHeight)
    return { width: max, height: min };
  else return { width: min, height: max };
}

function createFBO(w, h, type = gl.RGBA) {
  gl.activeTexture(gl.TEXTURE0);

  const texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  gl.texImage2D(gl.TEXTURE_2D, 0, type, w, h, 0, type, gl.FLOAT, null);

  const fbo = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
  gl.framebufferTexture2D(
    gl.FRAMEBUFFER,
    gl.COLOR_ATTACHMENT0,
    gl.TEXTURE_2D,
    texture,
    0
  );
  gl.viewport(0, 0, w, h);
  gl.clear(gl.COLOR_BUFFER_BIT);

  return {
    fbo,
    width: w,
    height: h,
    attach(id) {
      gl.activeTexture(gl.TEXTURE0 + id);
      gl.bindTexture(gl.TEXTURE_2D, texture);
      return id;
    },
  };
}

function createDoubleFBO(w, h, type) {
  let fbo1 = createFBO(w, h, type);
  let fbo2 = createFBO(w, h, type);

  return {
    width: w,
    height: h,
    texelSizeX: 1 / w,
    texelSizeY: 1 / h,
    read: () => {
      return fbo1;
    },
    write: () => {
      return fbo2;
    },
    swap() {
      let temp = fbo1;
      fbo1 = fbo2;
      fbo2 = temp;
    },
  };
}

function render() {
  const dt = (Date.now() - prevTimestamp) / 1000;
  prevTimestamp = Date.now();

  if (!pointer.firstMove) {
    pointer.moved = true;
    const newX =
      (0.65 +
        0.2 *
          Math.cos(0.006 * prevTimestamp) *
          Math.sin(0.008 * prevTimestamp)) *
      window.innerWidth;
    const newY =
      (0.5 + 0.12 * Math.sin(0.01 * prevTimestamp)) * window.innerHeight;
    pointer.dx = 10 * (newX - pointer.x);
    pointer.dy = 10 * (newY - pointer.y);
    pointer.x = newX;
    pointer.y = newY;
  }

  if (pointer.moved) {
    pointer.moved = false;

    gl.useProgram(splatProgram.program);
    gl.uniform1i(splatProgram.uniforms.u_input_txr, velocity.read().attach(0));
    gl.uniform1f(splatProgram.uniforms.u_ratio, canvas.width / canvas.height);
    gl.uniform2f(
      splatProgram.uniforms.u_point,
      pointer.x / canvas.width,
      1 - pointer.y / canvas.height
    );
    gl.uniform3f(
      splatProgram.uniforms.u_point_value,
      pointer.dx,
      -pointer.dy,
      1
    );
    gl.uniform1f(splatProgram.uniforms.u_point_size, params.SPLAT_RADIUS);

    blit(velocity.write());
    velocity.swap();

    gl.uniform1i(
      splatProgram.uniforms.u_input_txr,
      outputColor.read().attach(0)
    );
    gl.uniform3f(
      splatProgram.uniforms.u_point_value,
      1 - params.color.r,
      1 - params.color.g,
      1 - params.color.b
    );
    blit(outputColor.write());
    outputColor.swap();
  }

  gl.useProgram(divergenceProgram.program);
  gl.uniform2f(
    divergenceProgram.uniforms.u_vertex_texel,
    velocity.texelSizeX,
    velocity.texelSizeY
  );
  gl.uniform1i(
    divergenceProgram.uniforms.u_velocity_txr,
    velocity.read().attach(0)
  );
  blit(divergence);

  gl.useProgram(pressureProgram.program);
  gl.uniform2f(
    pressureProgram.uniforms.u_vertex_texel,
    velocity.texelSizeX,
    velocity.texelSizeY
  );
  gl.uniform1i(pressureProgram.uniforms.u_divergence_txr, divergence.attach(0));
  for (let i = 0; i < params.PRESSURE_ITERATIONS; i++) {
    gl.uniform1i(
      pressureProgram.uniforms.u_pressure_txr,
      pressure.read().attach(1)
    );
    blit(pressure.write());
    pressure.swap();
  }

  gl.useProgram(gradientSubtractProgram.program);
  gl.uniform2f(
    gradientSubtractProgram.uniforms.u_vertex_texel,
    velocity.texelSizeX,
    velocity.texelSizeY
  );
  gl.uniform1i(
    gradientSubtractProgram.uniforms.u_pressure_txr,
    pressure.read().attach(0)
  );
  gl.uniform1i(
    gradientSubtractProgram.uniforms.u_velocity_txr,
    velocity.read().attach(1)
  );
  blit(velocity.write());
  velocity.swap();

  gl.useProgram(advectionProgram.program);
  gl.uniform2f(
    advectionProgram.uniforms.u_vertex_texel,
    velocity.texelSizeX,
    velocity.texelSizeY
  );
  gl.uniform2f(
    advectionProgram.uniforms.u_output_textel,
    velocity.texelSizeX,
    velocity.texelSizeY
  );

  gl.uniform1i(
    advectionProgram.uniforms.u_velocity_txr,
    velocity.read().attach(0)
  );
  gl.uniform1i(
    advectionProgram.uniforms.u_input_txr,
    velocity.read().attach(0)
  );
  gl.uniform1f(advectionProgram.uniforms.u_dt, dt);
  gl.uniform1f(
    advectionProgram.uniforms.u_dissipation,
    params.VELOCITY_DISSIPATION
  );
  blit(velocity.write());
  velocity.swap();

  gl.uniform2f(
    advectionProgram.uniforms.u_output_textel,
    outputColor.texelSizeX,
    outputColor.texelSizeY
  );
  gl.uniform1i(
    advectionProgram.uniforms.u_velocity_txr,
    velocity.read().attach(0)
  );
  gl.uniform1i(
    advectionProgram.uniforms.u_input_txr,
    outputColor.read().attach(1)
  );
  gl.uniform1f(
    advectionProgram.uniforms.u_dissipation,
    params.DENSITY_DISSIPATION
  );
  blit(outputColor.write());
  outputColor.swap();

  gl.useProgram(displayProgram.program);
  gl.uniform1i(
    displayProgram.uniforms.u_output_texture,
    outputColor.read().attach(0)
  );
  blit();

  requestAnimationFrame(render);
}

This is the final file , you need to combine all the files.


Want to download zip file : click here

Want to See Live Demo  : click here




Canvas Layout:

First select the <canvas> element and set its width and height to match your client's dimensions.

Parameter Settings: 
The Params object sets various simulation parameters, including simulation and dye resolution, dissipation rates, pressure iterations, splat radius, and initial color
Signal management:
The basic configuration of the pointer object, which controls the position and movement of the user input. It has properties like x, y, dx, dy, moved, and firstMove.


Other Features:

The pointer has a delay (window.setTimeout) before allowing the first phase, possibly for the first setup phase.
The code adds a function (blit) to translate to the framebuffer.

Animation :

The simulation is updated based on the elapsed time (dt) from the previous frame using the requestAnimationFrame.


Breakdown of activities:


Initialization:


    Get a description of the canvas element.
    Set the initial parameters for the simulation.
    Include information about HTML elements such as paragraphs.
    Start a WebGL presentation on the canvas.
    Creates framebuffer objects (FBOs) to store simulation data.
    It also compiles the shader program load for different rendering stages.

    Translation loop:


    It uses requestAnimationFrame to repeatedly call the render function.
    Calculate the time delta (dt) between frames.
    Updates the pointer position based on user input or automatic movement.
    Uses speed and color "splats" instead of pointers.
    Calculates velocity deviations with shader program.
    The shader resolves compression by iterating the program.
    It absorbs the pressure gradient from velocity to promote incompressibility.
    It enters (moves) the velocity and color fields depending on the velocity field.
    Displays the last color output on the canvas.


    In summary, this code implements real-time fluid simulation using WebGL, including user interaction through mouse and touch input. The simulation includes several steps and is updated as a continuous rendering loop. Shaders and WebGL programming are used to achieve visual effects of water dynamics.


    No comments

    Powered by Blogger.