LoginSignup
12
4

WebGL で色々な表現に挑戦する - とにもかくにも canvas に描画する

Last updated at Posted at 2023-12-01

この記事の概要

HTML, CSS だけと比べて、WebGL を用いると表現力がアップします。
しかし WebGL や canvas に関連する記事が割と少なく、頑張って学んでいる最中です。
学んだ内容について、備忘録を兼ねて記事を書いていきます。

canvas 要素は、ただ HTML 上に配置したところでなんの効力も発揮しません。
描画領域を提供するだけで、その領域内に描画するための内容は含まれないからです。

実際の描画は、JavaScriptを使用して canvas 要素の描画コンテキストに命令を送ることで行われるのですが、一度にたくさんのことをやろうとすると複雑になります。
そのため、この記事では非常に簡単な内容だけを説明します。

バンドラーの設定

バンドラーは無くても動かせますが、今後の色々を考えてセットアップしておきます。
自分はパッケージマネージャーとして Bun を使っていて、Vite で環境を構築しました。

bunx create-vite

フレームワークは無し(Vanilla)で、TavaScriptを選択しました。

Canvas 以外の準備

Vite の雛形を使った都合で不要なファイルが存在しています。
ひとまずこれらを削除しました。

  • src/counter.ts
  • src/typescript.svg

次に index.html を変更します。

  <body>
-   <div id="app"></div>
+   <canvas id="webgl-canvas"></canvas>
    <script type="module" src="/src/main.ts"></script>
  </body>

src/style.css は、ファイル自体は残したままで、デフォルトのスタイルをリセットする程度の内容に変更します。

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

#webgl-canvas {
  display: block;
  height: 100dvh;
  width: 100dvw;
}

また、src/main.ts の中身を一旦すべて消します。

- import './style.css'
- import typescriptLogo from './typescript.svg'
- import viteLogo from '/vite.svg'
- import { setupCounter } from './counter.ts'
- 
- document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
-   <div>
-     <a href="https://vitejs.dev" target="_blank">
-       <img src="${viteLogo}" class="logo" alt="Vite logo" />
-     </a>
-     <a href="https://www.typescriptlang.org/" target="_blank">
-       <img src="${typescriptLogo}" class="logo vanilla" alt="TypeScript logo" />
-     </a>
-     <h1>Vite + TypeScript</h1>
-     <div class="card">
-       <button id="counter" type="button"></button>
-     </div>
-     <p class="read-the-docs">
-       Click on the Vite and TypeScript logos to learn more
-     </p>
-   </div>
- `
- 
- setupCounter(document.querySelector<HTMLButtonElement>('#counter')!)

Canvas そのものの準備

先ほど中身をすべて削除した src/main.ts に手を加えます。

分かりやすさ重視で型アサーションを使っています。

+ const canvas = document.getElementById("webgl-canvas") as HTMLCanvasElement;
+ const gl = canvas.getContext("webgl2") as WebGL2RenderingContext;
+ 
+ console.log(gl);

コンソールを見てみます(見やすいように整形してます)。

WebGL2RenderingContext {
  canvas: canvas#webgl-canvas,
  drawingBufferWidth: 300,
  drawingBufferHeight: 150,
  drawingBufferColorSpace: 'srgb',
  unpackColorSpace: 'srgb'
}

webgl のコンテキストが無事に取得できています(まだ画面は真っ白ですが、それであっています)。

確認できたので削除します。

  const canvas = document.getElementById("webgl-canvas") as HTMLCanvasElement;
  const gl = canvas.getContext("webgl2") as WebGL2RenderingContext;

- console.log(gl);

次に、シーン描画のための処理を書きます。

  const canvas = document.getElementById("webgl-canvas") as HTMLCanvasElement;
  const gl = canvas.getContext("webgl2") as WebGL2RenderingContext;

+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);

これで、画面が真っ白から真っ黒へ変わったと思います。

clearColor で指定した色で塗りつぶされ、指定できるのは r, g, b, a です。
今は 0.0, 0.0, 0.0, 1.0 を指定しているため真っ黒ですが、仮に 1.0, 0.0, 0.0, 1.0 を指定した場合は真っ赤になります。

一度、色々な色を指定してみてください。

最後に

今回はここまでです。

正直この内容であれば div 要素を配置して background-color を指定した方が早いし分かりやすいです。

しかし、これから先の複雑な表現のための足がかりなので、一旦堪えてください。

次の記事はこちらです。

12
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
4