結論

テクスチャとは、3DCGやWebGLで物体の表面に貼り付ける画像(色・凹凸・つやの情報)のことです。ふだんの言葉では「手触り・質感」を指し、料理や化粧品では食感・使用感の意味で使われます。

この記事でわかること

  • 場面別の意味と、CGのテクスチャ・マテリアル・シェーダーの違い
  • WebGLで画像を1枚貼る最小のコードと、フィルタ・ミップマップの差の画素値
  • テクスチャの容量・圧縮・2のべき乗と、CSSの背景画像との違い

2026年10月29日更新|Chromium 153(WebGL・SwiftShader)・Pillow 12.3で実行確認

この記事で実際に動かしたもの:自作のチェッカー画像と木目風の画像を Chromium の WebGL に貼り、readPixels で画素値を読み、CSS の背景画像と並べて撮影しました。

テクスチャは「画像ファイル」のままでは使われません。ブラウザやゲームエンジンが画像を画素の並びに戻し、GPU のメモリへ送り、描くたびにシェーダーが UV 座標から色を拾います。流れを図にすると次のとおりです。

flowchart TD
    A[画像ファイル<br>PNG・JPEG・WebP] --> B[デコード<br>RGBAの画素の並び]
    B --> C[GPUへ転送<br>texImage2D]
    C --> D[ミップマップ生成<br>縮小版を自動で作る]
    D --> E[シェーダーがUV座標から<br>色を取り出す]
    E --> F[画面の画素]

よく調べられることの答えを先にまとめます。

知りたいこと 答え 詳しい節
テクスチャとは(意味) CGでは表面に貼る画像。ふだんは手触り・質感 テクスチャとは(場面別の意味)
テクスチャとマテリアルの違い テクスチャは画像、マテリアルは見え方の設定一式 テクスチャ・マテリアル・シェーダーの違い
テクスチャの貼り方(WebGL) texImage2Dで送り、シェーダーのtexture2Dで読む 最初の5分
テクスチャがぼやける・ギザギザ 拡大時のフィルタ(LINEARかNEAREST)の違い テクスチャのフィルタ
遠くの模様がちらつく ミップマップを作る。斜めなら異方性フィルタも ミップマップとは
テクスチャが真っ黒になる WebGL1の2のべき乗以外の画像+REPEATなど テクスチャの大きさと2のべき乗
テクスチャの容量 1024×1024は約4MiB(ミップマップ込み約5.3MiB) テクスチャの容量とテクスチャ圧縮
CSSの背景画像との違い CSSは平面に敷くだけ。テクスチャは形に沿って貼る Webのテクスチャ

確認環境:Ubuntu 24.04.5 LTS の仮想環境で、GPU は無く(/dev/dri が無い)、WebGL は CPU によるソフトウェア描画(ANGLE+SwiftShader、Vulkan 1.3.0)で動いています。ブラウザは Google Chrome for Testing 153.0.8010.12(Chromium。playwright 1.63.0 でヘッドレス起動、Node.js 22.23.4)で、開いたのは Python 3.13.18 の http.server で 127.0.0.1 に置いた自作のページだけです。別オリジンの画像は、ポート番号を変えた 127.0.0.1 の自作サーバーから配りました。テクスチャに使った画像はすべて Pillow 12.3.0 と JavaScript で自分で作ったもので、他者の画像は使っていません。結果は readPixels で読んだ画素値と、ページのスクリーンショットで確かめています。実在の GPU を積んだ PC やスマホでは、上限の値や速さが変わります。WebGL の仕様上の制限は MDN の WebGL チュートリアルと WebGL best practices、テクスチャの語の歴史と種類は Wikipedia の「テクスチャマッピング」、CSS の拡大方法は MDN の image-rendering、KTX 2.0 は Khronos の公式ページで確かめました。図は mermaid で描画を確かめています(確認日 2026年10月29日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「テクスチャとは|CGとWebでの意味・ミップマップを実測で解説」

テクスチャとは(場面別の意味)

この節では、「テクスチャ」が分野ごとに何を指すのかと、ふだんの意味とITでの意味の違いが分かります。

テクスチャ(texture)は、英語で「織り目・手触り・質感」を表す言葉です。もとは織物の目の細かさを指す語で、そこから「物の表面の感じ」全般に広がりました。表記は「テクスチャ」「テクスチャー」「テクスチュア」と揺れますが、指すものは同じです。

場面 テクスチャの意味 例
ふだんの言葉 手触り・肌触り・質感 「ざらっとしたテクスチャの紙」
料理・食品 食感・口当たり 「なめらかなテクスチャのムース」
美容・化粧品 塗ったときの使用感・伸び 「みずみずしいテクスチャの乳液」
ファッション・建築 生地や壁・床材の表面の風合い 「凹凸のあるテクスチャの塗り壁」
音楽・写真・美術 音の重なり方、写真の質感、絵の表面の感じ 美術では「マチエール」とほぼ同じ場面で使う
3DCG・ゲーム モデルの表面に貼る画像(色・凹凸・つや) 球に木目の画像を貼って木の玉に見せる
Web・WebGL GPUに送ってシェーダーから読む画像データ WebGLのgl.TEXTURE_2D、three.jsのTexture

ふだんの意味とITでの意味

ふだん触ったとき・食べたときの「感じ」。形の無い性質を言う言葉
↔
IT・CGその「感じ」を見た目で出すための画像データ。幅×高さの画素の並びとして実在する

見分ける問い:「ファイルやメモリとして存在するか」

美術用語のマチエール(フランス語の matière)は、絵の具の盛り上がりや筆の跡など「作品の表面の材質感」を指します。CGで「マチエール」と言うことはほとんどなく、画像として扱うものはテクスチャと呼びます。

3DCGのテクスチャの仕組み(UV座標とテクスチャマッピング)

この節では、平らな画像を立体の表面にどう対応させるのか(UV座標・UV展開)が分かります。

テクスチャを形に貼る作業をテクスチャマッピングと呼び、画像のどこを形のどこに貼るかを「UV座標」で決めます。画像の横方向を U、縦方向を V とし、左下を (0, 0)、右上を (1, 1) とする 0〜1 の数で表します。3D の座標 X・Y・Z と区別するために、別の文字を使っています。

テクスチャマッピングは、1974年にユタ大学のエドウィン・キャットマルらが開発した手法とされます。形(ポリゴン)を細かくしなくても、画像で模様や質感を足せるため、少ない計算で見た目の情報量を増やせます。代わりに、細かさは画像の解像度で決まり、近づくとぼやけます。

1

モデリング

形(ポリゴン)を作る。この時点では表面は単色。

Blender など

2

UV展開

立体の表面を切り開いて平らに並べる。地球儀を世界地図にするのと同じ考え方で、切れ目を「シーム」と呼ぶ。白黒のチェッカー画像を貼って、ます目が伸びていないかで歪みを確かめる。

歪み・テクセル密度を見る

3

ベイク・ペイント

細かい形の凹凸を画像に焼き付ける(ベイク)か、3Dペイントのソフトで直接描く。数式で模様を作るプロシージャルテクスチャという方法もある。

Substance 3D Painter など

4

マテリアルに設定

色・凹凸・つやの画像をマテリアルの各欄につなぐ。

ゲームエンジン・WebGLへ

5

ライトの下で確かめる

光の向きを変えて、つやや凹凸が意図どおりに見えるかを見る。遠くから見たときのちらつきも確かめる。

レンダリング

テクセル密度は、表面の一定の広さに何画素(テクセル。テクスチャの1画素)が割り当たっているかです。同じ場面で物によって密度が大きく違うと、一部だけぼやけて見えます。UV展開をしない方法として、平面・円筒・球の形で画像を投影する方法もあります。

テクスチャ・マテリアル・シェーダーの違い(PBRのマップの種類)

この節では、混同しやすいテクスチャ・マテリアル・シェーダーの関係と、テクスチャの種類(マップ)が分かります。

テクスチャは「画像」、マテリアルは「見え方の設定一式」、シェーダーは「その設定から画素の色を計算するプログラム」です。マテリアルの中に、テクスチャが材料として入ります。

1テクスチャ

色・凹凸・つやなどを画素ごとに持つ画像。単体では「どう光るか」は決まらない。

2マテリアル

色・金属っぽさ・粗さなどの値と、使うテクスチャの組み合わせ。「木の床」「さびた鉄」のような素材の定義。

3シェーダー

GPUで動くプログラム。マテリアルの値とテクスチャ、光の向きから、画面の1画素ごとの色を計算する。

色が変なら「テクスチャ」、つや・透け方が変なら「マテリアルの値」、ソフトによって見え方が違うなら「シェーダー」を疑う、という切り分けができます。今のゲームエンジンや Blender の多くは、物理の法則に沿って光を計算する PBR(物理ベースレンダリング)を使い、役割の違うテクスチャを何枚も組み合わせます。

マップ(テクスチャ) 持っている情報 見え方への効き方
ベースカラー(アルベド・ディフューズ) 表面そのものの色 模様・色。いちばん基本の1枚
ノーマル(法線)マップ 画素ごとの面の向き(青紫っぽい画像) 形を変えずに細かい凹凸の陰影を出す
ハイト・バンプマップ 高さ(白いほど高い) 凹凸。ディスプレイスメントでは形そのものを動かす
ラフネス(粗さ) 表面のざらつき 反射のぼけ方。つるつるか、つや消しか
メタリック 金属か、そうでないか 反射の色の付き方
AO(アンビエントオクルージョン) すき間の暗さ 溝やくぼみに落ちる影
エミッション・オパシティ(アルファ) 自ら光る部分、透明度 発光、葉っぱや金網の抜け

このほか、周りの景色の写り込みを出す環境マップ(立方体の6面に画像を並べたキューブマップ)、光源から見た深さで影を作るシャドウマップ、煙や霧に使う3次元のボリュームテクスチャもあります。WebGL2 では、この環境の Chromium で 3次元テクスチャの1辺の上限(MAX_3D_TEXTURE_SIZE)が 2048 でした。

最初の5分:WebGLでテクスチャを1枚貼る最小のコード

この節では、ブラウザだけでテクスチャを貼る最小の手順と、その結果の画素値が分かります。

WebGL では、テクスチャを作り(createTexture)、画素を送り(texImage2D)、フィルタを決め(texParameteri)、シェーダーの texture2D で読みます。画像ファイルを読み込む前に、2×2 画素のテクスチャを自分で作って貼るのがいちばん短い例です。左下が赤、右下が緑、左上が青、右上が黄の4画素です。

<canvas id="c" width="8" height="8"></canvas>
<script>
const gl = document.getElementById('c').getContext('webgl', { preserveDrawingBuffer: true });
const vs = `attribute vec2 p; attribute vec2 uv; varying vec2 v;
  void main(){ v = uv; gl_Position = vec4(p, 0., 1.); }`;
const fs = `precision mediump float; varying vec2 v; uniform sampler2D t;
  void main(){ gl_FragColor = texture2D(t, v); }`;
const sh = (type, src) => { const s = gl.createShader(type); gl.shaderSource(s, src); gl.compileShader(s); return s; };
const prog = gl.createProgram();
gl.attachShader(prog, sh(gl.VERTEX_SHADER, vs));
gl.attachShader(prog, sh(gl.FRAGMENT_SHADER, fs));
gl.linkProgram(prog); gl.useProgram(prog);

// 画面いっぱいの四角形(位置 x,y と UV u,v)
const data = new Float32Array([-1,-1,0,0,  1,-1,1,0,  -1,1,0,1,  1,1,1,1]);
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
const lp = gl.getAttribLocation(prog, 'p'), lu = gl.getAttribLocation(prog, 'uv');
gl.enableVertexAttribArray(lp); gl.vertexAttribPointer(lp, 2, gl.FLOAT, false, 16, 0);
gl.enableVertexAttribArray(lu); gl.vertexAttribPointer(lu, 2, gl.FLOAT, false, 16, 8);

// 2x2 のテクスチャ(下の行: 赤 緑 / 上の行: 青 黄)
const px = new Uint8Array([255,0,0,255, 0,255,0,255, 0,0,255,255, 255,255,0,255]);
gl.bindTexture(gl.TEXTURE_2D, gl.createTexture());
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, px);
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.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
</script>

8×8 の canvas に描き、readPixels で全画素を読んで色の名前に直した結果です(上の行から表示)。4画素の画像が、1色あたり 4×4 画素に拡大されて貼られました。

B B B B Y Y Y Y
B B B B Y Y Y Y
B B B B Y Y Y Y
B B B B Y Y Y Y
R R R R G G G G
R R R R G G G G
R R R R G G G G
R R R R G G G G

TEXTURE_MIN_FILTER を省くと、真っ黒になります。既定値は NEAREST_MIPMAP_LINEAR(getTexParameter で 0x2702)で、ミップマップがある前提の設定だからです。4×4 の灰色(200)のテクスチャで、MIN_FILTER を決めずに描くと readPixels は (0,0,0,255)、generateMipmap を呼んでから描くと (200,200,200) でした。コンソールには何も出ませんでした。

画像ファイルを使うときは、px の代わりに読み込み終わった Image を渡し、gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img) とします。MDN のチュートリアルは、画像が届くまで1画素の仮の色を入れておき、すぐ描けるようにする書き方を紹介しています。WebGL そのものの仕組み(GPU・canvas・使えないときの直し方)は、別記事「WebGLとは|仕組み・使い方・使えないときの直し方をエラー原文で」で扱っています。この記事はその中の「テクスチャ」に絞った入口です。

テクスチャのフィルタ(NEARESTとLINEAR)の違いを画素値で見る

この節では、テクスチャを拡大・縮小したときに「くっきり」と「なめらか」が何で決まるのかが分かります。

テクスチャの1画素と画面の1画素はふつう一致しないので、間の色をどう決めるか(フィルタ)を選びます。NEAREST はいちばん近い1画素の色をそのまま使い、LINEAR は周りの4画素を距離に応じて混ぜます。拡大のときは TEXTURE_MAG_FILTER、縮小のときは TEXTURE_MIN_FILTER で別々に決めます。

上の 2×2 のテクスチャを LINEAR にして同じ 8×8 に描くと、境目に中間の色ができました。readPixels の値(R, G, B)です。

B B (32,32,223) (96,96,159) (159,159,96) (223,223,32) Y Y
(32,0,223) (32,0,223) (56,32,195) (104,96,139) (151,159,84) (199,223,28) (223,255,0) (223,255,0)
(159,0,96) (159,0,96) (151,32,84) (135,96,60) (120,159,36) (104,223,12) (96,255,0) (96,255,0)
R R (223,32,0) (159,96,0) (96,159,0) (32,223,0) G G

(8行のうち、2・3・5・6行目を表示)赤から緑へ、223→159→96→32 と4段で移り変わっています。真ん中付近は (120,96,100) のような灰色がかった色で、4色が混ざった結果です。

NEAREST(最近傍)

境目がくっきり。ドット絵・ピクセルアート向き

拡大すると四角いブロックが見える

縮小すると模様が崩れやすい

LINEAR(双線形)

境目がなめらか。写真・木目・肌向き

拡大するとぼやける

拡大(MAG_FILTER)の既定値

ミップマップとは(遠くのテクスチャがちらつく理由)

この節では、テクスチャを小さく表示したときに起きるちらつき(エイリアシング)と、ミップマップ・異方性フィルタの効き目が分かります。

ミップマップは、テクスチャの縮小版(1/2、1/4、1/8…)をあらかじめ作っておき、表示の大きさに合った版から色を取る仕組みです。WebGL では gl.generateMipmap(gl.TEXTURE_2D) の1行で作れます。縮小版を全部足しても元の約1/3なので、メモリは約1.33倍になります(MDN は「約30%の上乗せ」と説明しています)。

1画素ごとに白黒が入れ替わる 256×256 のチェッカー画像を、37×37 画素の canvas に縮小して描き、画素の明るさを集計しました。理想は全面が灰色(128付近・ばらつき0)です。

TEXTURE_MIN_FILTER 平均 標準偏差 最小〜最大
NEAREST(ミップマップなし) 127.4 127.5 0〜255
LINEAR(ミップマップなし) 127.5 42.4 7〜248
NEAREST_MIPMAP_NEAREST 128 0 128〜128
LINEAR_MIPMAP_LINEAR(トライリニア) 128 0 128〜128

ミップマップが無いと、平均は灰色でも1画素ごとに真っ白と真っ黒がばらばらに出ました(標準偏差127.5)。これが、遠くの床や網の模様がちらついたり、縞模様(モアレ)が出たりする原因です。ミップマップを使うと、縮小版のほうで色がすでに平均されているので、きれいな灰色になりました。

次に、32画素のます目のチェッカー画像(自作)を奥に向かって倒した床に貼り、4つの設定で描いて、奥のほう(画面の上から約1/4の帯、100×30画素)の明るさのばらつきを測りました。

50.9NEAREST(ミップマップなし)奥がモアレで崩れる
15.6LINEAR_MIPMAP_LINEARちらつきは消えるが奥がぼける
21.4ミップマップ+異方性16倍崩れずに模様が少し残る

数値は明るさの標準偏差です(ミップマップなしの LINEAR は 50.5)。奥の模様はもともと細かすぎて画面の画素では表せないため、値が大きいほど「崩れた模様が出ている」ことを示します。ただし、ミップマップだけだと斜めの面では縦方向に合わせて小さい版が選ばれ、横方向までぼけます。そこで EXT_texture_filter_anisotropic(異方性フィルタ)を使うと、斜め方向に何回か色を取り直して、ぼけを抑えます。この環境の上限(MAX_TEXTURE_MAX_ANISOTROPY_EXT)は 16 でした。

  1. 1NEAREST最も軽い。縮小すると崩れる
  2. 2LINEAR拡大はなめらか。大きく縮小すると崩れる
  3. 3LINEAR_MIPMAP_NEAREST(バイリニア+ミップマップ)版の切り替わりに境目の線が出ることがある
  4. 4LINEAR_MIPMAP_LINEAR(トライリニア)2つの版の間も混ぜる。3Dの基本の選び方
  5. 5トライリニア+異方性フィルタ斜めの床・道路で最もきれい。計算は増える

テクスチャの繰り返し(REPEAT・CLAMP_TO_EDGE・MIRRORED_REPEAT)

この節では、UV座標が 0〜1 をはみ出したときにテクスチャがどう貼られるかが分かります。

床のタイルや壁のレンガのように同じ模様を敷き詰めたいときは、UV座標を 1 より大きくして「繰り返し(ラップ)」の方法を選びます。横方向は TEXTURE_WRAP_S、縦方向は TEXTURE_WRAP_T です。2×2 のテクスチャを UV 0〜3 の範囲で 12画素の帯に描き、上の行(青・黄)を読みました。

WRAP の設定 readPixelsの結果(左から12画素) 使いどころ
REPEAT B B Y Y B B Y Y B B Y Y タイル・芝生・レンガの敷き詰め
CLAMP_TO_EDGE B B Y Y Y Y Y Y Y Y Y Y 1枚絵・UI・継ぎ目を見せたくない端
MIRRORED_REPEAT B B Y Y Y Y B B B B Y Y 継ぎ目が目立つ模様を折り返して隠す

CLAMP_TO_EDGE は端の1画素の色を引き伸ばし、MIRRORED_REPEAT は1回ごとに左右を反転しました。敷き詰め用の画像は、端と端がつながるように作った「シームレステクスチャ」を使います。たくさんの小さな画像を1枚にまとめて読み込みを減らす方法を「テクスチャアトラス」、建物の縁取りなどを細長い帯にまとめたものを「トリムシート」と呼びます。

テクスチャの大きさと2のべき乗(WebGL1の制限とWebGL2)

この節では、テクスチャの幅・高さを 256・512・1024 のような2のべき乗にする理由と、そうしないと何が起きるかが分かります。

WebGL1 では、2のべき乗でないテクスチャは「CLAMP_TO_EDGE」と「ミップマップなし(NEAREST か LINEAR)」の組み合わせでしか使えません。MDN は、この設定にしないと、そのテクスチャから取る色は透明な黒になると説明しています。300×200(2のべき乗でない)のテクスチャを、明るさ200の灰色で塗って試しました。

設定(300×200のテクスチャ) WebGL1の結果 WebGL2の結果
CLAMP_TO_EDGE+LINEAR (200,200,200) 正しく表示 (200,200,200) 正しく表示
既定のREPEAT+LINEAR (0,0,0,255) 真っ黒。警告なし (200,200,200) 正しく表示
generateMipmap を呼ぶ 真っ黒。getError() は 1282 (200,200,200) 正しく表示

WebGL1 で generateMipmap を呼んだときは、コンソールに次の警告が出ました(1282 は INVALID_OPERATION の番号です)。

[.WebGL-0x16ec001bd000] GL_INVALID_OPERATION: glGenerateMipmap: The texture is a non-power-of-two texture.

一方、REPEAT のまま描いたときは、この環境ではコンソールに何も出ず、画面が黒くなっただけでした。MDN は「透明な黒」と書いていますが、手元の readPixels ではアルファが 255(不透明の黒)でした。原因が表示されないので、「テクスチャが真っ黒」のときは、まず画像の大きさと WRAP の設定を見るのが早道です。WebGL2(OpenGL ES 3.0 相当)では、どの組み合わせでも正しく表示されました。

  • 2のべき乗にするのは、WebGL1 の制限のためだけではありません。ミップマップは縦横を半分ずつにしていくので、2のべき乗だと最後の 1×1 まで割り切れます。素材集やゲームエンジンが 1024・2048・4096 で作るのはこのためです。
  • 上限もあります。この環境の Chromium では MAX_TEXTURE_SIZE が 8192、キューブマップは 16384、1回の描画で使えるテクスチャの数(MAX_TEXTURE_IMAGE_UNITS)は 32 でした。端末によって値が違うので、自分の環境は次の「自分で確かめる」節の1行で分かります。

テクスチャの容量とテクスチャ圧縮(ファイルサイズとGPUメモリは別)

この節では、テクスチャがメモリをどれだけ使うかと、テクスチャ圧縮(BC・ETC・ASTC)で何が変わるかが分かります。

PNG や JPEG の小ささは、GPU のメモリでは関係がありません。GPU に送る前に画素の並びへ戻すので、幅×高さ×4バイト(RGBA)になります。自作の木目風の画像(1024×1024)で比べました。

形 大きさ メモ
PNG ファイル 1,716,129 バイト(約1.6MiB) 可逆圧縮。ノイズの多い画像は縮みにくい
JPEG ファイル(品質85) 171,994 バイト(約168KiB) 非可逆。ダウンロードは軽い
WebP ファイル(品質85) 125,214 バイト(約122KiB) 非可逆。ダウンロードは最も軽い
GPU上(RGBA8・ミップマップなし) 4,194,304 バイト(4MiB) どのファイル形式から読んでも同じ
GPU上(RGBA8・ミップマップあり) 約5.33MiB 縮小版の分、約1.33倍
GPU上(BC1・ETC2 RGB) 524,288 バイト(0.5MiB) 4×4画素を8バイトに。RGBA8の1/8
GPU上(BC7・ASTC 4×4) 1,048,576 バイト(1MiB) 4×4画素を16バイトに。RGBA8の1/4

WebP にするとダウンロードは約1/14 になりますが、GPU 上の 4MiB は変わりません。GPU が直接読める形のまま小さくしたものが「テクスチャ圧縮」です。画像を4×4画素のかたまり(ブロック)ごとに決まったバイト数に縮めるので、描くときも縮めたまま読めます。

この環境の WebGL2 では、ETC・ETC1・S3TC(BC1〜3)・ASTC・BPTC(BC7)・RGTC が使え、PVRTC は使えませんでした。BC1 で「赤1色」の4×4ブロック(8バイト)を自分で書いて compressedTexImage2D で送ると、readPixels は (255,0,0,255) を返しました。ETC2 のブロックに 16バイトを渡すと、大きさが合わないとして次の警告になりました。

[.WebGL-0x16ec001b7000] GL_INVALID_VALUE: glCompressedTexImage2D: The <imageSize> does not match the expected data size for the format and dimensions of the compressed image.

MDN の WebGL best practices は、どの端末でも使える圧縮形式は1つも無く、デスクトップは S3TC、Android は ETC1、iOS は PVRTC が目安で、WebGL2 では S3TC と ETC の組み合わせで広く対応できると説明しています。形式を端末ごとに用意する代わりに、Basis Universal で1つのファイルにしておき、読み込むときにその端末の形式へ変換する方法があります。Khronos の KTX 2.0 は、この Basis Universal の圧縮を入れられる GPU テクスチャ用のファイル形式です。

転送の時間も測りました。texImage2D と generateMipmap をまとめて3回行った中央値は、512×512 で 1.0ms、2048×2048 で 7.5ms、4096×4096 で 28.9ms でした(GPU の無い SwiftShader での値で、1回ごとのばらつきもあります)。4096 は1枚で 64MiB(ミップマップ込み約85MiB)あるので、スマホでは枚数に気をつけます。

Webのテクスチャ:CSSの背景画像との違い

この節では、Webページの「テクスチャ背景」(CSS の background-image)と、WebGL のテクスチャの違いが分かります。

Web デザインで「テクスチャ」と言うと、紙・布・コンクリートのような質感の画像を背景に敷くことを指す場合が多く、これは CSS の background-image で作ります。CSS の背景は、四角い要素の上に画像を並べるだけで、形に沿って曲げたり、光に合わせてつやを変えたりはしません。

同じ 2×2 画素の画像(JavaScript の canvas で自作)を、CSS の背景として 160×160 に拡大し、スクリーンショットの画素を読みました。上の段(赤→緑)を左から10画素おきに並べたものです。

CSS の設定 赤から緑への変わり方(10画素おき) WebGLでいうと
image-rendering: auto(既定) (255,0,0)…(223,31,0)→(191,63,0)→(127,127,0)→…(0,255,0) LINEAR に近い
image-rendering: pixelated (255,0,0)が8回 → (0,255,0)が8回 NEAREST に近い

ブラウザの画像表示でも、拡大のしかたはテクスチャのフィルタと同じ考え方です。MDN は、auto はブラウザ次第(Firefox は双線形)、pixelated と crisp-edges は最近傍のような方法と説明しています。ドット絵を拡大してぼやけるときは、CSS なら image-rendering: pixelated、WebGL なら NEAREST にします。

比べる点 CSSの背景画像 WebGLのテクスチャ
貼る先 四角い要素の背景 どんな形の表面にも(UV座標で指定)
繰り返し background-repeat TEXTURE_WRAP_S・T(REPEATなど)
拡大の仕方 image-rendering TEXTURE_MAG_FILTER
光・凹凸 無し(影はbox-shadowなど別の機能) ノーマルマップなどとシェーダーで計算
別のサイトの画像 そのまま表示できる CORSの許可が無いと使えない

CSS の background の書き方(cover・中央寄せ・繰り返し)は、関連記事「CSS backgroundプロパティ一覧|cover・中央寄せ・繰り返し早見表」で扱っています。

自分の環境でテクスチャを確かめる(開発者ツール・ターミナル・chrome://gpu)

この節では、自分のブラウザ・画像で「テクスチャの上限」「画像の大きさとメモリ」「GPUで描いているか」をその場で確かめる方法が分かります。

次の3つは、手元で実際に打って結果を確かめたものです。

1. ブラウザの開発者ツールで1行(テクスチャの最大サイズ)

Chrome・Edge で F12(Mac は Command+Option+I)を押して「Console(コンソール)」を開き、次の1行を貼って Enter を押します。0x0D33 は MAX_TEXTURE_SIZE の番号です。

document.createElement('canvas').getContext('webgl').getParameter(0x0D33)

この環境では 8192 と返りました。これが、その端末で1枚のテクスチャに使える幅・高さの上限です。null のエラーになるときは、WebGL そのものが使えない状態です。

2. ターミナルで1行(画像の大きさと2のべき乗)

file wood_1024.png wood_1000.png
wood_1024.png: PNG image data, 1024 x 1024, 8-bit/color RGB, non-interlaced
wood_1000.png: PNG image data, 1000 x 1000, 8-bit/color RGB, non-interlaced

1000×1000 は2のべき乗ではないので、WebGL1 では REPEAT・ミップマップが使えません。GPU 上の大きさは次の1行で見積もれます(Python が入っていれば Windows・Mac でも同じです)。

python3 -c "w,h=1024,1024; b=w*h*4; print(b/2**20,'MiB', round(b*4/3/2**20,2),'MiB(+mip)')"
4.0 MiB 5.33 MiB(+mip)

3. 設定画面のどこを見るか(chrome://gpu)

Chrome のアドレスバーに chrome://gpu と入れると、WebGL・Canvas などの状態が一覧で出ます。この環境では次のように表示されました。GPU で動いていれば「Software only」ではなく「Hardware accelerated」などと表示されます。

*   Canvas: Software only, hardware acceleration unavailable
*   WebGL: Software only, hardware acceleration unavailable
  • 1コンソールで MAX_TEXTURE_SIZE を見た使う画像の幅・高さがこの値以下か
  • 2画像の幅・高さが2のべき乗か見たWebGL1でREPEAT・ミップマップを使うなら必須
  • 3GPUメモリを幅×高さ×4で見積もったミップマップを作るなら×1.33
  • 4chrome://gpu で WebGL の状態を見たSoftware only なら重い・遅いのは端末側の理由

テクスチャのよくあるエラー・つまずき(原文つき)

この節では、テクスチャが表示されない・崩れるときの症状と原因、手元で出たエラーの原文が分かります。

症状・エラーの原文 原因 直し方
テクスチャが真っ黒(警告なし) WebGL1で2のべき乗でない画像にREPEATやミップマップ CLAMP_TO_EDGE+LINEARにする、2のべき乗に直す、WebGL2を使う
GL_INVALID_OPERATION: glGenerateMipmap: The texture is a non-power-of-two texture. WebGL1で2のべき乗でない画像のミップマップを作ろうとした 画像を2のべき乗に直すか、ミップマップを作らない
2のべき乗の画像でも真っ黒(警告なし) MIN_FILTERの既定値がNEAREST_MIPMAP_LINEARで、ミップマップを求めている generateMipmapを呼ぶか、MIN_FILTERをLINEARにする
SecurityError: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The image element contains cross-origin data, and may not be loaded. 別オリジンの画像をCORSの許可なしで使った img.crossOrigin = 'anonymous' と、配信側の Access-Control-Allow-Origin
Access to image at '…' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. crossOriginを付けたが、配信側が許可ヘッダーを返していない 画像を配るサーバーの設定に許可ヘッダーを足す
GL_INVALID_VALUE: glCompressedTexImage2D: The <imageSize> does not match … 圧縮テクスチャのバイト数が形式・大きさと合わない 形式(ブロックのバイト数)と幅・高さを見直す
WARNING: Too many active WebGL contexts. Oldest context will be lost. canvasを作りすぎて、先に作ったものから捨てられた canvasを使い回す。不要なものはWEBGL_lose_contextで解放
遠くの模様がちらつく・縞が出る ミップマップなしで縮小している generateMipmap+LINEAR_MIPMAP_LINEAR、斜めなら異方性フィルタ
ドット絵がぼやける 拡大のフィルタがLINEAR(CSSならauto) NEAREST(CSSならimage-rendering: pixelated)
画像が上下逆さま 画像は上から、WebGLのUVは下から数える UNPACK_FLIP_Y_WEBGLを有効にするか、UVのvを反転

CORS の2つのエラーは、ポートだけ変えた 127.0.0.1 の自作サーバーで再現しました。crossOrigin を付けない画像は表示自体はできても、WebGL に渡す時点で SecurityError になります。crossOrigin を付けると、配信側に許可ヘッダーが無い場合は画像の読み込みそのものが失敗し、許可ヘッダーを返すようにすると getError() が 0 で貼れました。MDN も、WebGL のテクスチャはクロスドメインの制限を受け、file:/// の URL からは読めないため、確かめるときも Web サーバーが要ると説明しています。

真っ黒・表示されないときの調べ方

やってはいけないコードを当てずっぽうに書き換える。HTMLファイルをダブルクリックで開いて確かめる
→
代わりにコンソールの警告を読み、gl.getError() の番号を見て、画像の大きさとWRAP・フィルタの設定を1つずつ確かめる。ローカルでもWebサーバー経由で開く

1281はINVALID_VALUE、1282はINVALID_OPERATION

判断表:テクスチャの設定と形式をどう選ぶか

この節では、作るものに合わせて、フィルタ・繰り返し・大きさ・形式をどう選ぶかが一覧で分かります。

作るもの フィルタ・ミップマップ 繰り返し・大きさ・形式
3Dの床・地面・道路 LINEAR_MIPMAP_LINEAR+異方性フィルタ REPEAT。2のべき乗。数が多いなら圧縮テクスチャ
3Dのキャラクター・小物 LINEAR_MIPMAP_LINEAR CLAMP_TO_EDGE。PBRのマップを数枚。1024〜2048
ドット絵・ピクセルアートのゲーム NEAREST(ミップマップなし) CLAMP_TO_EDGE。PNG。整数倍で拡大
2DのUI・文字・アイコン LINEAR(縮小しないならミップマップなし) CLAMP_TO_EDGE。拡大縮小が多いならSVGを検討
写真を1枚見せるだけ LINEAR WebGLを使わずimgタグとCSSで足りることが多い
Webページの質感のある背景 CSSのimage-rendering: auto background-repeat。WebP・JPEGで軽く
スマホ向けの3D(メモリが少ない) LINEAR_MIPMAP_LINEAR KTX 2.0(Basis Universal)で端末の圧縮形式へ

WebP や JPEG の画像の扱い(変換・圧縮率)は関連記事「WebP・HEICとは|JPG・PNGへの変換と画像圧縮を実測で解説」、拡大しても崩れない画像は関連記事「SVGファイルとは|PNGとの違い・開き方・作り方を実測で解説」で扱っています。テクスチャ用の画像を 1024 などの大きさにそろえる処理は、関連記事「Python Pillowで画像処理|リサイズ・トリミング・形式変換のコード集」のコードでできます。ゲームエンジンでスプライト(2Dの画像)やテクスチャを使ってみるなら、関連記事「Godot Engineとは|始め方・GDScript・2Dゲームの作り方を解説」が入口になります。

テクスチャを作るソフトは、画像編集ソフト(GIMP・Photoshop など)、3Dペイントのソフト(Substance 3D Painter など)、統合型の3DCGソフト(Blender など)に分かれ、Unity・Unreal Engine・Godot などのゲームエンジンに読み込んで使います。素材サイトの画像を使うときは、商用利用・再配布・クレジット表記の条件をそれぞれのライセンスで確かめます。

よくある質問

この節では、テクスチャについてよく調べられる疑問への短い答えが分かります。

Q. テクスチャとテクスチャーは違うものですか。
同じものです。英語の texture をカタカナにしたときの表記の揺れで、「テクスチュア」と書かれることもあります。

Q. テクスチャとマテリアルの違いは何ですか。
テクスチャは画像、マテリアルは色・粗さ・金属っぽさなどの値とテクスチャをまとめた「素材の設定」です。マテリアルの中にテクスチャが入ります。

Q. テクスチャマッピングとは何ですか。
画像を3Dの形の表面に貼る手法です。画像のどこを形のどこに貼るかを UV 座標で決めます。1974年に開発された、3DCGの基本の技術です。

Q. テクスチャの解像度は大きいほどよいですか。
近くで見る物ほど大きいほうがきれいですが、1024×1024 でも GPU 上で約4MiB、4096×4096 なら64MiBを使います。画面に映る大きさに合わせ、ミップマップと圧縮テクスチャで節約します。

Q. テクスチャの大きさは必ず2のべき乗にしますか。
WebGL1 で REPEAT やミップマップを使うなら必須です。WebGL2 では手元の確認で 300×200 でも全部の設定で表示できましたが、ミップマップが割り切れるため、素材は 2のべき乗で作るのが一般的です。

Q. ミップマップを作るとメモリはどれくらい増えますか。
元の約1/3(約1.33倍)です。縮小しない2Dの画像では作らない、という選び方もあります。

Q. ゲームの「テクスチャ品質」の設定を下げると何が変わりますか。
一般に、使うテクスチャの解像度(ミップマップのどの版から使うか)が下がり、GPU のメモリが減る代わりに近くの物がぼやけます。具体的な中身はゲームごとに違うため、各ゲームの説明で確かめます。

Q. WebGLで別のサイトの画像をテクスチャにできないのはなぜですか。
CORS の制限のためです。画像を配るサーバーが Access-Control-Allow-Origin を返し、読み込む側で crossOrigin を付けたときだけ使えます。許可の無い画像では SecurityError になりました。

Q. Webデザインの「テクスチャ素材」とCGのテクスチャは同じですか。
どちらも質感を出すための画像ですが、Webデザインでは CSS の背景として平面に敷き、CGでは形に沿って貼って光の計算にも使います。

Q. 料理や化粧品の「テクスチャ」はどういう意味ですか。
料理では食感・口当たり、化粧品では塗ったときの伸びや使用感を指します。どちらも「触れたときの感じ」という元の意味から来ています。

まとめ

この節では、テクスチャについて押さえる点を5つにまとめます。

  • テクスチャとは、CGでは表面に貼る画像、ふだんの言葉では手触り・質感のこと。料理なら食感、化粧品なら使用感の意味になる。
  • 画像のどこを形のどこに貼るかはUV座標で決める。テクスチャは画像、マテリアルは素材の設定、シェーダーは色を計算するプログラム。
  • 拡大縮小の見え方はフィルタで決まる。NEAREST はくっきり、LINEAR はなめらか。縮小するならミップマップ(手元でばらつき127.5→0)。
  • WebGL1 では2のべき乗でない画像にREPEAT・ミップマップを使うと真っ黒になる。警告が出ない場合もあるので、大きさと設定を先に見る。
  • GPU上の容量は幅×高さ×4バイトで、ファイル形式に関係しない。減らすならテクスチャ圧縮(BC・ETC・ASTC、KTX 2.0)。

参考・出典

確認日はいずれも 2026年10月29日です。

  • MDN「Using textures in WebGL」:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL
  • MDN「WebGL best practices」:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices
  • MDN「WebGLRenderingContext: texParameter[fi]() method」:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texParameter
  • MDN「EXT_texture_filter_anisotropic」:https://developer.mozilla.org/en-US/docs/Web/API/EXT_texture_filter_anisotropic
  • MDN「WebGLRenderingContext: pixelStorei() method」:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/pixelStorei
  • MDN「image-rendering」:https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering
  • Khronos「KTX - GPU Texture Container Format」:https://www.khronos.org/ktx/
  • Khronos「WebGL Specification」:https://registry.khronos.org/webgl/specs/latest/1.0/
  • Wikipedia「テクスチャマッピング」:https://ja.wikipedia.org/wiki/テクスチャマッピング

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「テクスチャとは|CGとWebでの意味・ミップマップを実測で解説」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ
参加受付中

AI駆動開発、 無料セミナー