glium(https://github.com/tomaka/glium)のexamplesにあるtessellation
プログラム(tessellation.rs)を参考にして、David Wolff著「OpenGL 4.0
シェーディング言語 ( OpenGL 4.0 Shading Language Cookbook )」の6章
「ジオメトリシェーダとテッセレーションシェーダ」をgliumで書いてみました。
今回は、「曲線をテッセレートする」の項です。テッセレーションの方法で、
曲線を描きます。
実行結果
tessellation level = 3
tessellation level = 5
tessellation level = 8
この例では、曲線の描画に3次べジェ曲線(ブレンド関数はベルンシュタイン
多項式)を使うので、4個の制御点(コントロールポイント)が必要です。
この4個の制御点がパッチ プリミティブになります。
1 コントロールポイントの設定
let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: [-0.8, -0.8] }, Vertex { position: [-0.4, 0.8] }, Vertex { position: [ 0.4, -0.8] }, Vertex { position: [ 0.8, 0.8] }, ] ).unwrap() };
VertexBufferを使ってコントロールポイントの頂点座標を設定します。
2 パッチ プリミティブとパッチあたりの頂点数を設定
let indices = glium::index::NoIndices( PrimitiveType::Patches { vertices_per_patch: 4 });
IndexBufferのPrimitiveTypeとvertices_per_patchで、パッチ プリミティブの
使用とパッチあたりの頂点数を設定します。
3 シェーダプログラムの設定
let program = glium::Program::new(&display, glium::program::SourceCode { vertex_shader: " #version 140 in vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", tessellation_control_shader: Some(" #version 400 layout(vertices = 4) out; uniform int tess_level = 5; void main() { gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; gl_TessLevelOuter[0] = 1; gl_TessLevelOuter[1] = tess_level; } "), tessellation_evaluation_shader: Some(" #version 400 layout(isolines) in; void main() { float u = gl_TessCoord.x; vec3 p0 = gl_in[0].gl_Position.xyz; vec3 p1 = gl_in[1].gl_Position.xyz; vec3 p2 = gl_in[2].gl_Position.xyz; vec3 p3 = gl_in[3].gl_Position.xyz; float u1 = (1.0 - u); float u2 = u * u; float b3 = u2 * u; float b2 = 3.0 * u2 * u1; float b1 = 3.0 * u * u1 * u1; float b0 = u1 * u1 * u1; vec3 p = p0 * b0 + p1 * b1 + p2 * b2 + p3 * b3; gl_Position = vec4(p, 1.0); } "), geometry_shader: None, fragment_shader: " #version 140 out vec4 f_color; void main() { f_color = vec4(1.0, 1.0, 1.0, 1.0); } ", }).unwrap();
このプログラムでは、バーテックスシェーダ、テッセレーション制御シェーダ、
テッセレーション評価シェーダを使用します。このような場合は、Programの
SourceCodeを使って設定します。
テッセレーションシェーダとジオメトリシェーダはOptionとして設定するので、
None(使用しない)かSome()(使用する場合)で設定します。
曲線の描画では、Innerレベルは使用しません。Outerレベルでは、Outer[0]を1、
Outer[1]にレベルを設定します。GPUによっては、入れ替えが必要な場合が
あります。