Skip to content

レンダリング (1.20.1)

解説する必要のある事柄が多すぎるため、レンダリングするうえでの最小限の知識を解説しています。

技術スタック

GPU

GPUで描画されている。

OpenGL

グラフィックスドライバと通信するための規格。

ステートマシンとなっているため、設定した値は戻すまで状態が維持されます。

そこでバニラのメソッドはうまくラッピングし、カバーしています。

LWJGL

MinecraftはLWJGLというライブラリを経由してOpenGLで描画しています。

基本的にはOpenGLのコマンドを直接叩くことは少なく、用意されたAPIを通して描画します。

Blaze3D

MinecraftがOpenGLを直接叩く代わりに用意した静的クラス群。

Mod制作では、GLコマンドを直接叩くのではなく、用意されたAPI(RenderSystem等)を通して描画します。

JOML

数学ライブラリとしては主にJOMLが使用されています。

座標系

座標系は大きく3つあり、それぞれ異なる用途を持っています。 (Minecraftにおいて明確に定義されているわけではない)

それらの座標系は主に PoseStack によって操作、管理されています。 (レンダリングAPIで解説)

様々な座標系がありますが、結果的にはスクリーン座標系に変換され描画されます。

ワールド座標系

ゲーム内のブロックやエンティティが存在する絶対的な座標。

ゲーム内で通常使うXYZ座標がこれにあたります。

  • X+: 東 (East)
  • Y+: 上 (Up)
  • Z+: 南 (South)

ビュー座標系

カメラを中心とした座標系。

スクリーン座標系

インベントリ画面やHUD(ホットバー、体力等)を描画する際の2D座標。

原点(0,0): 画面の左上隅。

  • X+ 右へ
  • Y+ 下へ (ワールド座標とYの向きが逆なので注意!)
  • Z+: 奥(深度+)

ローカル座標系

個々のオブジェクトを中心とした相対的な座標系。

座標変換

基本的に以下の流れで座標変換されます。

graph LR
    L[ローカル座標系] --> W[ワールド座標系];
    W --> V[ビュー座標系];
    V --> S[スクリーン座標系];

テクスチャ座標(UV)

モデルの頂点には、テクスチャのどの部分を貼り付けるかという情報(UV)を持たせます。

スクリーン座標系と同じ軸と原点を持っていて、U,Vどちらも範囲は0.0~1.0です。

  • 開始位置: (u0, v0)
  • 終了位置: (u1, v1)

を持ちます。

Info

JSONモデルでは、UVはピクセル単位で指定しますが、シェーダーに送られる際には、テクスチャアトラス内での位置として変換されたUV値として扱われます。

描画方法

頂点

OpenGLにおいて、すべての物体は頂点の集まりによって構成されています。

頂点とは、3Dモデルを構成する最小単位の点のことです。

主な値(Minecraftにおいて)

  • Position: 位置情報
  • Color: 色情報
  • UV: テクスチャ座標
  • Normal(法線): 光の当たり方等を計算するために必要
  • ライトマップ: 光のテクスチャ
  • オーバーレイテクスチャ: ダメージ表現やTNTの点滅等に使われるテクスチャのUVの指定

レンダリングパイプライン

ラスタライズ

頂点で構成された図形を、フラグメントに変換する処理。

塗りつぶすピクセルごとに頂点の情報(色、UV、法線等)を線形補間して割り当てます。

フラグメント(Fragment)

ピクセルになる前の計算途中のデータです。

ピクセル座標、深度値、テクスチャ座標等、線形補間されたデータを持ちます。

Fragment Shader

フラグメントシェーダーは、フラグメントの情報を元に、最終的な色を決定するシェーダープログラムです。

つまり、描画する色を決定するシェーダープログラムです。

position_color.fsh
#version 150

in vec4 vertexColor;

uniform vec4 ColorModulator;

out vec4 fragColor;

void main() {
    vec4 color = vertexColor;
    if (color.a == 0.0) {
        discard;
    }
    fragColor = color * ColorModulator;
}

Vertex Shader

頂点シェーダーは、頂点の情報を元に、最終的な位置を決定するシェーダープログラムです。

position_color.vsh
#version 150

in vec3 Position;
in vec4 Color;

uniform mat4 ModelViewMat;
uniform mat4 ProjMat;

out vec4 vertexColor;

void main() {
    gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0);

    vertexColor = Color;
}