Buat Efek Bulge Warp Menggunakan WebGL

 – Beragampengetahuan
9 mins read

Buat Efek Bulge Warp Menggunakan WebGL – Beragampengetahuan

Distorsi di WebGL sangat menarik. Baru-baru ini, saya harus membuat efek yang disebut “Bulge” untuk sebuah proyek di situs web Upperquad.com. Berikut adalah video singkat yang menunjukkannya.

Idenya adalah untuk menciptakan distorsi yang berasal dari suatu titik dan mendorong segala sesuatu di sekitarnya. Di Adobe After Effects, Anda dapat menggunakan Bulge Effect untuk mencapainya. Ini memungkinkan Anda untuk “menumbuhkan” area tertentu dari suatu gambar, mirip dengan meniup gelembung untuk membuatnya mengembang. Efek ini dapat menciptakan beberapa efek visual yang menarik.

Anda juga dapat membalikkan efek ini.

Dalam tutorial singkat ini, kita akan menjelajahi cara membuat efek tonjolan pada tekstur menggunakan OGL, pustaka WebGL ringan yang dikembangkan oleh Nathan Gordon. Untuk mencapai efek ini, Anda memerlukan pemahaman dasar tentang JavaScript, WebGL, dan shader. Namun, Anda juga dapat langsung mengunduh demo dan mencoba kodenya jika Anda mau.

Contents

1. Memulai

Pertama, mari buat adegan WebGL 2D dasar menggunakan OGL. Anda dapat mengunduh dan memulai dari repositori template ini, yang mencakup semua yang Anda butuhkan.

Di template ini, Anda sudah memiliki tag kanvas HTML dengan CSS untuk menjadikannya layar penuh. Dalam JavaScript, Anda dapat menyiapkan perender, program dengan shader dan uniform, dan mesh yang merender sekitar 60 bingkai per detik. Template juga menyertakan fitur pengubahan ukuran. Shader program menampilkan latar belakang gradien animasi. Mereka datang:

// src/js/glsl/main.vert
attribute vec2 uv;
attribute vec2 position;
varying vec2 vUv;

void main() {
  vUv = uv;
  gl_Position = vec4(position, 0, 1);
}
// src/js/glsl/main.frag
uniform float uTime;
uniform vec3 uColor;
uniform float uOffset;
varying vec2 vUv;

void main() {
  gl_FragColor.rgb = 0.3 + 0.3 * cos(vUv.xyx * uOffset + uTime) + uColor;
  gl_FragColor.a = 1.0;
}

PS: Di OGL, ide Nathan Gordon adalah membuat jaring layar penuh dalam adegan dengan menggambar hanya 1 segitiga, bukan 2 segitiga (seperti yang biasa Anda lakukan saat membuat persegi panjang). UV kemudian digunakan untuk memetakan layar jendela. Pada dasarnya, ini seperti menempatkan persegi di dalam segitiga (seperti yang ditunjukkan di sebelah kanan) untuk menyimpan poin:

Hasilnya adalah sebagai berikut:

Lihat Kotak Pasir Kode

PS: Anda dapat mencapai adegan latar belakang seperti tiga.js dengan menggunakan ilmu ukur bidang dan a bahan shader.

2. Tampilkan tekstur di “background-cover”

Pertama, mari berkomitmen untuk memuat tekstur.Anda dapat memilih gambar apa pun yang Anda inginkan dan menempatkannya rakyat/ map.kita akan membuat sebuah gambar baru(), atur URL gambar sebagai sumber, dan muat.Lalu, gunakan Tekstur baru (ini.#renderer.gl) Dari OGL, kami mengonversinya menjadi tekstur dan melampirkan gambar ke dalamnya menggunakan atribut baru bernama .gambar.kami akan menggunakan asinkron/menunggu Pastikan tekstur kita dimuat sebelum membuat program WebGL.

// src/js/components/scene.js
// load our texture
const loadTexture = (url) =>
  new Promise((resolve) => {
    const image = new Image()
    const texture = new Texture(gl)

    image.onload = () => {
      texture.image = image
      resolve(texture)
    }

    image.src = url
  })

const texture = await loadTexture('./img/image-7.jpg')

Sekarang, mari tambahkan tekstur ke livery prosedural.

// src/js/components/scene.js
this.#program = new Program(gl, {
  vertex,
  fragment,
  uniforms: {
    uTime: { value: 0 },
    uTexture: { value: texture },
  },
})

di shader fragmen kami.

// src/js/glsl/main.frag
precision highp float;

uniform sampler2D uTexture;
varying vec2 vUv;

void main() {
  vec4 tex = texture2D(uTexture, vUv);
  gl_FragColor.rgb = tex.rgb;
  gl_FragColor.a = 1.0;
}

Lihat Kotak Pasir Kode

Dingin! Seperti yang Anda lihat, kami memiliki tekstur, tetapi terlihat melar.

Idealnya, kita ingin “memotong” tekstur dalam pemandangan dengan cara sebaik mungkin, apakah itu dalam format lanskap atau potret. Ada properti di CSS yang disebut “ukuran latar belakang: sampul” Secara ajaib mencapai efek ini, tetapi di WebGL, ini lebih rumit untuk dicapai.

Untungnya, saya memiliki sepotong kecil kode yang membuat UV berperilaku seperti itu “ukuran latar belakang: sampul” Pengaruh. Mari kita gunakan. Tapi pertama-tama, kita harus meneruskan resolusi gambar dan kanvas ke seragam kita.

// src/js/components/scene.js
...
uTextureResolution: { value: new Vec2(texture.image.width, texture.image.height) },
uResolution: { value: new Vec2(gl.canvas.offsetWidth, gl.canvas.offsetHeight) },
...

Mari tambahkan kliping UV ke vertex shader kita (./src/js/glsl/main.vert)

attribute vec2 uv;
attribute vec2 position;

uniform vec2 uResolution;
uniform vec2 uTextureResolution;

varying vec2 vUv;

vec2 resizeUvCover(vec2 uv, vec2 size, vec2 resolution) {
    vec2 ratio = vec2(
        min((resolution.x / resolution.y) / (size.x / size.y), 1.0),
        min((resolution.y / resolution.x) / (size.y / size.x), 1.0)
    );

    return vec2(
        uv.x * ratio.x + (1.0 - ratio.x) * 0.5,
        uv.y * ratio.y + (1.0 - ratio.y) * 0.5
    );
}

void main() {
  vUv = resizeUvCover(uv, uTextureResolution, uResolution);
  gl_Position = vec4(position, 0, 1);
}

jangan lupa untuk memperbarui resolusi saat mengubah ukuran “./src/js/components/scene.js”.

// src/js/components/scene.js
handleResize = () => {
  this.#renderer.setSize(window.innerWidth, window.innerHeight)

  if (this.#program) {
    this.#program.uniforms.uResolution.value = new Vec2(window.innerWidth, window.innerHeight)
  }
}

Lihat Kotak Pasir Kode

Sekarang setelah gambar kita terpotong, mari kita warpkan!

3. Distorsi gambar menggunakan efek Bulge

Untuk membuat efek tonjolan, kami ingin memindahkan UV sesuai dengan bagian tengah gambar. UV berkisar dari 0 hingga 1, di mana U mewakili piksel dari kiri ke kanan gambar dan V mewakili piksel dari bawah ke atas.

Untuk mencapai efek “tonjolan”, kita dapat mengalikan UV dengan jarak dari pusat.fungsi bawaan panjang() GLSL memberi kita panjang antar piksel, seperti yang dijelaskan di buku shader.Mari kita buat sebuah fungsi bernama efek tonjolan() untuk menangani perhitungan ini dan menerapkan UV yang dimodifikasi ke tekstur di shader fragmen.

// src/js/glsl/main.frag
vec2 bulge(vec2 uv) {
  
  float dist = length(uv); // distance from UVs top right corner
  uv *= dist; 

  return uv;
}

void main() {
  vec2 bulgeUV = bulge(vUv);
  vec4 tex = texture2D(uTexture, bulgeUV);
  gl_FragColor.rgb = tex.rgb;
  gl_FragColor.a = 1.0;
}

Distorsi tampaknya berasal dari pojok kanan bawah, bukan dari tengah. Untuk memperbaikinya, kita kurangi 0,5 dari UV sebelum melakukan perhitungan distorsi, lalu tambahkan kembali ke pusat distorsi.

// src/js/glsl/main.frag
vec2 bulge(vec2 uv, vec2 center) {
  uv -= center;
  
  float dist = length(uv); // distance from UVs
  uv *= dist; 
  
  uv += center;

  return uv;
}

void main() {
  vec2 center = vec2(0.5, 0.5);
  vec2 bulgeUV = bulge(vUv, center);
  vec4 tex = texture2D(uTexture, bulgeUV);
  gl_FragColor.rgb = tex.rgb;
  gl_FragColor.a = 1.0;
}

Lihat Kotak Pasir Kode

Ini bekerja, tetapi tidak terlalu kuat.

Menggunakan fungsi power sangat berguna untuk meningkatkan efek, dan glsl sudah memilikinya pow() Untuk kita. Mari kita coba 2.

  // src/js/glsl/main.frag
  ...
  float dist = length(uv); // distance from UVs
  float distPow = pow(dist, 2.); // exponential
  uv *= distPow; 

Lihat Kotak Pasir Kode

Sekarang, jika Anda ingin mengembalikan efeknya, Anda dapat membagi efek tonjolan dengan radius untuk kontrol yang lebih besar. Jangan ragu untuk menyesuaikan nilai-nilai ini sampai Anda mendapatkan efek yang diinginkan.

// src/js/glsl/main.frag
...
const float radius = 0.6;
const float strength = 1.1;

vec2 bulge(vec2 uv, vec2 center) {
  uv -= center;
  
  float dist = length(uv) / radius; // distance from UVs divided by radius
  float distPow = pow(dist, 2.); // exponential
  float strengthAmount = strength / (1.0 + distPow); // Invert bulge and add a minimum of 1)
  uv *= strengthAmount; 
  
  uv += center;

  return uv;
}

Lihat Kotak Pasir Kode

4. Tambahkan interaktivitas

Akhirnya, mari buat tonjolan melacak mouse melalui event mousemove. 🙂

mari kita gunakan a mouse Seragam untuk ini.

// src/js/components/scene.js
...
// In the uniform's Program
uMouse: { value: new Vec2(0.5, 0.5) },
...

...
  // Add event listener
  window.addEventListener('mousemove', this.handleMouseMove, false)
...
...
// On mouse move we want the this.#mouse value to be
// between 0 and 1 X and Y axis
handleMouseMove = (e) => {
  const x = e.clientX / window.innerWidth
  const y = 1 - e.clientY / window.innerHeight

  this.#mouse.x = x
  this.#mouse.y = y

  // update the uMouse value here or in the handleRAF
  this.#program.uniforms.uMouse.value = this.#mouse
}
...
...

Kemudian di shader fragmen, kita cukup mengganti tengah bersama kami mouse.

// src/js/glsl/main.frag
uniform vec2 uMouse;
...
   vec2 bulgeUV = bulge(vUv, uMouse);
...

Itu dia 🙂 Arahkan kursor untuk melihatnya beraksi:

Lihat Kotak Pasir Kode

Tentu saja, Anda dapat menambahkan efek apa pun yang Anda inginkan. Misalnya, Anda dapat memainkan animasi GSAP untuk mengatur ulang efek saat mouse meninggalkan kanvas, seperti yang ditampilkan di demo, atau menambahkan efek apa pun yang dapat Anda bayangkan 🙂

Kami telah melihat bahwa warping dapat dengan mudah ditangani di WebGL hanya dengan shader fragmen sederhana, dan kami juga dapat memperoleh banyak efek lainnya. Jika Anda ingin mempelajari cara membuat jenis distorsi lain menggunakan tekstur noise, saya mengundang Anda untuk menonton salah satu tutorial saya yang lain tentang subjek tersebut. bersulang!

mengacu pada

Tulis efek hover gambar berubin dari Quai Network

rencana pengembangan website



metode pengembangan website

jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website

#Buat #Efek #Bulge #Warp #Menggunakan #WebGL

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *