はじめに
最近、Unityの環境周りのトラブルに振り回されて、開発が思うように進まず、トラウマ気味になってるので、久しぶりにThree.jsの記事を書いてみます。
復習的な内容で過去記事とかぶるかもしれません。
ただ、Unityもこれだけ長時間環境周りを弄り倒したので、かなり詳しくなったのも事実です。
上手くいってると、変に設定を弄ると、壊れるのが怖くて、腫れ物に触る感じでインセプターやhierarchyを変更しませんでしたが、 トラブルの影響で、弄り倒したので、ほんとシステムや、ライブラリ周り、GUIについて詳しくなったのも事実です。
Three.jsのように、すべてコードで管理した方が早いし、バックアップも楽で、デバックもしやすいのではないかと思ったりしますね…。
C#で何もかも設定できた方が個人的には分かりやすいし、gitでの管理も楽で、開発も進みそうな気がします。
Three.jsで、ゲームエンジンの構造理解をし過ぎたせいで、Unityのブラックボックスと独自仕様に振り回されてるきがしますし、システムが不安定な6000台を最初に触ったのもタイミングが悪かった気がします。
それでも、すべてを触ったことが何もかもスキルアップになってはいますが…。
自分でエンジンを実装しなくていいのは楽な反面、ブラックボックスの独自仕様を理解しないと傷めを見るというのもよくわかりました。
1. はじめに:gl_FragCoordとは?
gl_FragCoord は Fragment Shader(フラグメントシェーダー)内で自動的に使えるビルトイン変数 です。 Three.js でも Unity(HLSL)でも “画面に描かれるピクセルごとの情報” を扱うときの基本になります。
シンプルに言うと ——
💡 「今、この1ピクセルが画面上のどこに描かれているか?」 を教えてくれる値。
これだけでできることは多く、たとえば:
- 画面全体のグラデーション
- スキャンライン(縞模様)
- 画面の中心から円を広げる
- ポストプロセス効果(ブラー、波紋、ゆがみ)
など、“画面効果の基礎中の基礎” になる。
ピクセル単位で処理できるので、 Three.js の ShaderMaterial やポストプロセスの練習で最初に触れる概念として最適。
2. gl_FragCoord の中身
gl_FragCoord は 4つの要素(vec4) でできている。
gl_FragCoord = vec4(x, y, z, w);
それぞれの役割は次の通り。
.x, .y:画面上のピクセル位置(そのまま整数)
- .x → 左からの距離(ピクセル)
- .y → 下からの距離(ピクセル)
たとえば 1920×1080 の画面なら:
- 左下 → (0, 0)
- 右上 → (1920, 1080)
この2つは 最もよく使う値 で、 グラデーション・スキャンライン・ビジュアライザ系エフェクトの土台になる。
.z:深度(depth)
.z は 深度バッファの値が入っている。
- 0.0 → 画面側(近い)
- 1.0 → 奥(遠い)
Three.js の場合は ポストプロセスで depth を扱う時に使える。
Unity でいう _CameraDepthTexture の fragment 版。
.w:1 / clip.w(クリップ空間の奥行きの逆数)
これは少し専門的だけど、 遠近感の補正(透視補正)に使える値 になっている。
普段の用途ではほぼ触らないが、
- 高度なポストエフェクト
- 位置再構築(view space の復元)
- デプスノーマルの合成
- SSAO/SSR などの計算
では .z より .w のほうが役立つ場面がある。
まとめ
| 要素 | 意味 | よく使う場面 |
|---|---|---|
| .x | ピクセルのX位置 | グラデーション、横方向のエフェクト |
| .y | ピクセルのY位置 | スキャンライン、縦方向のエフェクト |
| .z | 深度(0〜1) | 透明度、フォグ、奥行き表現 |
| .w | 1/clip.w | 高度なポストプロセス |
gl_FragCoord は“画面シェーダーの地図”みたいなもの。 この4要素がわかると、画面効果の理解が一気に進む。
3. よくある用途
gl_FragCoord は “画面そのものを操作する” ときに非常に便利で、 ポストプロセスや画面効果の基本はほぼこれで作れる。 ここでは、実際に使われる代表的な用途をまとめる。
① グラデーション(上下・左右)
gl_FragCoord.y(縦位置)や x(横位置)を使えば、 画面全体にスムーズなグラデーションを簡単に作れる。
float t = gl_FragCoord.y / resolution.y;
vec3 color = mix(colorA, colorB, t);
- 上から下へ
- 左から右へ
- 中央から外へ
など、ピクセル位置がそのまま補間の値になる。
② ラインパターン(周期的な模様)
mod() を組み合わせると、 等間隔の 横線・縦線 を作れる。
float line = step(0.95, fract(gl_FragCoord.y * 0.05));
- HUD風のUI
- グリッド演出
- レトロゲーム風のパターン
によく使われる。
③ スキャンライン(CRT / レトロ演出)
画面全体に細い横線を入れる“スキャンライン”も gl_FragCoord.y の偶奇で簡単に表現できる。
float scan = mod(gl_FragCoord.y, 2.0) < 1.0 ? 0.05 : 1.0;
- CRTモニタ風
- アナログ感
- ノイズ表現
など、映像系の演出に便利。
④ UV の代わりに画面全体の処理をしたい時
通常の vUv(0〜1 のUV)を使わずに、 画面のピクセル位置をそのままUVの代わりにするパターン。
vec2 uv = gl_FragCoord.xy / resolution.xy;
これにより:
- ポストプロセス
- フルスクリーンエフェクト
- ブラー
- ディストーション
- 波紋エフェクト
などの “画面全体のエフェクト” を簡単に書ける。
Three.jsで自作ポストプロセスを書くなら 最初に覚えるべき構造。
まとめ
gl_FragCoord は 「画面を1ピクセル単位で読む指標」。
- 位置 → グラデーション
- 位置 → ライン・スキャンライン
- 位置 → UV代替
- z → デプス
- w → 高度なポストプロセス
多くの表現が “位置を数式に入れるだけ” で作れるようになる。
4. Three.js の最小コードサンプル(gl_FragCoord を使う)
ここでは、画面全体にシェーダーを描画する最小の例を示す。 Three.js では ShaderMaterial と、 フルスクリーンクワッド(plane)を使って描画するのが定番。
JavaScript側(最小)
const renderer = new THREE.WebGLRenderer({ antialias: true });
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
const geometry = new THREE.PlaneGeometry(2, 2);
const material = new THREE.ShaderMaterial({
uniforms: {
resolution: { value: new THREE.Vector2() },
time: { value: 0.0 }
},
vertexShader: `
void main() {
gl_Position = vec4(position, 1.0);
}
`,
fragmentShader: `
uniform vec2 resolution;
uniform float time;
void main() {
// gl_FragCoord を 0〜1 に正規化
vec2 uv = gl_FragCoord.xy / resolution;
// シンプルなグラデーション(Y方向)
float t = uv.y;
gl_FragColor = vec4(vec3(t), 1.0);
}
`
});
const quad = new THREE.Mesh(geometry, material);
scene.add(quad);
function resize() {
renderer.setSize(window.innerWidth, window.innerHeight);
material.uniforms.resolution.value.set(window.innerWidth, window.innerHeight);
}
window.addEventListener("resize", resize);
resize();
function animate(t) {
material.uniforms.time.value = t * 0.001;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate();
🔍 解説ポイント
1. フルスクリーン描画の定番構成
PlaneGeometry(2,2) を使って
画面全体にシェーダー1枚を貼るという構成。
Three.js のポストプロセスを書くときの基本形。
2. gl_FragCoord を UV の代わりに使う
vec2 uv = gl_FragCoord.xy / resolution;
これで、UV が 0〜1 の画面位置 に変換される。
- (0,0) → 左下
- (1,1) → 右上
Three.js の標準的な UV と同じ感覚で使える。
3. 縦グラデーションの例
float t = uv.y;
gl_FragColor = vec4(vec3(t), 1.0);
gl_FragCoord の基本用途として最も分かりやすい例。
5. まとめ
gl_FragCoord は、
「今描いているピクセルが画面のどこなのか」
を直接教えてくれる、Fragment Shader の基礎中の基礎。
- .x, .y → 位置(ピクセル座標)
- .z → depth(0〜1)
- .w → 1 / clip.w(透視補正用の値)
Three.js で画面全体のシェーダーを書くとき、
この4つが分かっていれば グラデーション・スキャンライン・パターン生成 など
ほとんどの画面効果を作れるようになる。
そして実際に動かしてみると、
“UVではなく、画面のピクセル位置そのものを使う”
という考え方が一気に理解できる。
ポストプロセスや自作Shaderに挑戦するなら、
gl_FragCoord を土台にして、
少しずつ 色・ノイズ・時間・深度 を組み合わせていくと
Three.js の表現力は一気に広がる。
この記事で基礎は押さえたので、
次は応用として:
- ノイズ(Perlin / Simplex)
- ディストーション
- ブラー
- デプスを使った透明度
- 波紋エフェクト
などに進むとスムーズに理解が深まるはず。
💬 コメント