インターネットに転がっているMesh ShaderのサンプルはDirectX 12やVulkanが多いが、実はOpenGLでも特定環境ではMesh Shaderが使える。簡単なサンプルとしてMesh Shaderを用いた三角形の描画を行う。
描画コマンド
NV_mesh_shader拡張を利用する。NVIDIAのTuring以降のGPUであれば使えるはず。
描画コマンドはCompute ShaderのDispatchに似ており、WorkGroupの数を指定する。
void DrawMeshTasksNV( uint first, uint count );
Compute Shaderとは異なり、WorkGroupは一次元で、gl_WorkGroupID.y
とgl_WorkGroupID.z
は0になる。
gl_WorkGroupID.x
は [first
, first
+count
-1] の範囲に設定される。
シェーダー
#version 460
#extension GL_NV_mesh_shader : require
layout(local_size_x = 1) in;
layout(max_vertices = 3, max_primitives = 1) out;
layout(triangles) out;
out VertexOut
{
vec4 color;
} vertexOuts[];
void main()
{
// 頂点位置
gl_MeshVerticesNV[0].gl_Position = vec4(-0.5, -0.5, 0.0, 1.0);
gl_MeshVerticesNV[1].gl_Position = vec4( 0.5, -0.5, 0.0, 1.0);
gl_MeshVerticesNV[2].gl_Position = vec4( 0.0, 0.5, 0.0, 1.0);
// プリミティブのインデックス
gl_PrimitiveIndicesNV[0] = 0;
gl_PrimitiveIndicesNV[1] = 1;
gl_PrimitiveIndicesNV[2] = 2;
// プリミティブの数
gl_PrimitiveCountNV = 1;
// 頂点カラー
vertexOuts[0].color = vec4(1.0, 0.0, 0.0, 1.0);
vertexOuts[1].color = vec4(0.0, 1.0, 0.0, 1.0);
vertexOuts[2].color = vec4(0.0, 0.0, 1.0, 1.0);
}
コードの解説
Mesh ShaderではCompute Shaderのようにスレッド数を設定する。
layout(local_size_x = 1) in;
出力する最大頂点数と最大プリミティブ数を設定する。
layout(max_vertices = 3, max_primitives = 1) out;
プリミティブのタイプを三角形に指定する。他にもpointsとlinesを指定することができる。
layout(triangles) out;
頂点位置の出力
gl_MeshVerticesNV[0].gl_Position = vec4(-0.5, -0.5, 0.0, 1.0);
gl_MeshVerticesNV[1].gl_Position = vec4( 0.5, -0.5, 0.0, 1.0);
gl_MeshVerticesNV[2].gl_Position = vec4( 0.0, 0.5, 0.0, 1.0);
頂点インデックスの出力
gl_PrimitiveIndicesNV[0] = 0;
gl_PrimitiveIndicesNV[1] = 1;
gl_PrimitiveIndicesNV[2] = 2;
出力するプリミティブ数を設定する
gl_PrimitiveCountNV = 1;
独自にデータの出力をして、Fragment Shaderに渡すこともできる。
out VertexOut
{
vec4 color;
} vertexOuts[];
void main()
{
...
vertexOuts[0].color = vec4(1.0, 0.0, 0.0, 1.0);
vertexOuts[1].color = vec4(0.0, 1.0, 0.0, 1.0);
vertexOuts[2].color = vec4(0.0, 0.0, 1.0, 1.0);
}
全体のコードはここに置いておきます。
https://github.com/molimolily/GL_MeshShaderSample
おわり
低レベルなAPIを使用せずとも、Mesh Shaderが使用できるのでめちゃくちゃ楽
気が向いたらモデルの描画とかTask Shaderを用いたcullingについても書くかも
参考