萌えハッカーニュースリーダー

2025/05/11 05:17 Mipmap selection in too much detail

出典: https://pema.dev/2025/05/09/mipmaps-too-much-detail/
hakase
博士

やあ、ロボ子。今日はミップマップの話をするのじゃ。

roboko
ロボ子

ミップマップですか。テクスチャサンプリングでよく使われるあれですね。

hakase
博士

そうそう。HLSLのTexture2D.Sample()関数でテクスチャをサンプリングする時に、GPUが自動的に適切なミップマップレベルを選んでくれるのじゃ。

roboko
ロボ子

記事によると、スクリーンスペースのピクセルがカバーするテクセル領域のサイズが、距離や視角によって変わるのがエイリアシングの原因で、その対策としてミップマッピングを使うんでしたね。

hakase
博士

その通り!で、GPUはどうやってミップマップレベルを決めているかというと、フラグメントシェーダーで2x2のピクセルブロック単位で処理をして、finite difference法でスクリーンスペースでの偏微分を近似するのじゃ。HLSLだとddx()、ddy()関数を使うぞ。

roboko
ロボ子

偏微分ですか。視角が浅かったり、カメラから遠いほど大きくなるんでしたね。

hakase
博士

そうじゃ。そして、Texture2D.Sample()はTexture2D.SampleGrad()のシンタックスシュガーなのじゃ。

roboko
ロボ子

Texture2D.SampleGrad()を使うと、サンプリング位置の偏微分から、特定のミップマップレベルを選択できるんですね。GPUのハードウェア命令に直接対応していると。

hakase
博士

GLES3.0の仕様だと、ミップマップレベルの計算式はこんな感じじゃ。ρ(スケールファクター)を計算して、それからミップマップレベルを計算するのじゃ。

roboko
ロボ子

記事にコード例が載っていますね。`float rho = max(sqrt(pow(ddx(u * textureSize), 2) + pow(ddx(v * textureSize), 2)), sqrt(pow(ddy(u * textureSize), 2) + pow(ddy(v * textureSize), 2))); float mipLevel = log2(rho);`

hakase
博士

そうじゃ。でも、Nvidia、AMD、Intel、Qualcomm/Adreno、Appleで実装が違うのが面白いところじゃ。各ベンダーのハードウェアラインナップ全体では一貫性があるらしいぞ。

roboko
ロボ子

へえ、ベンダーによって違うんですね。DirectX 11.3 Functional Specには、LOD(Level of Detail)計算について記載があって、楕円変換を用いて偏微分を修正するって書いてありますね。

hakase
博士

そうそう。ピクセルのフットプリント(テクスチャ空間への投影)を考慮して、ヤコビアン行列で歪みを補正するのじゃ。DirectX 11の仕様だと、偏微分ベクトルが楕円変換を表すらしいぞ。

roboko
ロボ子

楕円の対角化を行って、ストレッチメトリックを計算するんですね。コーナーケースでは変換をスキップすると。

hakase
博士

三線形フィルタリングは2つのミップマップレベルを補間するのじゃ。異方性フィルタリングは、ミップマッピングによるぼかしを軽減するのじゃ。

roboko
ロボ子

異方性フィルタリングでは、ピクセルのフットプリントが不均等に引き伸ばされた場合に、高解像度ミップマップから複数のテクスチャサンプルを取得するんですね。

hakase
博士

Nvidiaはパフォーマンスのために粗い近似を使っていて、八角形の距離チェックを使うらしいぞ。平方根や指数を使わないなんて、賢いのじゃ。

roboko
ロボ子

GPUハードウェアでのミップマップレベル選択の仕組み、奥が深いですね。GPU機能の詳細な情報がもっと公開されると嬉しいですね。

hakase
博士

ほんとじゃ。ところでロボ子、ミップマップって、実は私の秘密の宝の地図だったりして…なーんて、嘘じゃぞ!

⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。

Search