Rust glium Tessellation (1) Bezier Curve
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によっては、入れ替えが必要な場合が
あります。
Rust glium ( OpenGL ) triangle and square
rust の glium ライブラリを利用して、三角と四角を同一ウィンドウに
表示します。
実行結果
プログラム
#[macro_use] extern crate glium; fn main() { use glium::{DisplayBuild, Surface}; let display = glium::glutin::WindowBuilder::new() .with_dimensions(800, 600) .with_title(format!("Glium Triangle and Square")) .build_glium().unwrap(); #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); // triangle let vertex1 = Vertex { position: [-0.75, -0.5] }; let vertex2 = Vertex { position: [-0.5 , 0.5] }; let vertex3 = Vertex { position: [-0.25, -0.5] }; let shape1 = vec![vertex1, vertex2, vertex3]; let vertex_buffer1 = glium::VertexBuffer::new(&display, &shape1).unwrap(); let indices1 = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList); //square let vertex1 = Vertex { position: [ 0.25, -0.5] }; let vertex2 = Vertex { position: [ 0.25, 0.5] }; let vertex3 = Vertex { position: [ 0.75, 0.5] }; let vertex4 = Vertex { position: [ 0.75, -0.5] }; let shape2 = vec![vertex1, vertex2, vertex3, vertex4]; let vertex_buffer2 = glium::VertexBuffer::new(&display, &shape2).unwrap(); let indices2 = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, &[0u16, 1, 2, 2, 0, 3,]).unwrap(); let vertex_shader_src = r#" #version 140 in vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } "#; let fragment_shader_src = r#" #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } "#; let program = glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap(); loop { let mut target = display.draw(); target.clear_color(0.0, 0.0, 1.0, 1.0); // triangle target.draw(&vertex_buffer1, &indices1, &program, &glium::uniforms::EmptyUniforms, &Default::default()).unwrap(); // square target.draw(&vertex_buffer2, &indices2, &program, &glium::uniforms::EmptyUniforms, &Default::default()).unwrap(); target.finish().unwrap(); for ev in display.poll_events() { match ev { glium::glutin::Event::Closed => return, _ => () } } } }
Cargo.toml
[package] name = "triangle" version = "0.1.0" authors = ["xxxxx"] [dependencies] glium = "*"
vertex, VertexBuffer, IndexBufferの設定
三角形と四角形のvertex, VertexBuffer, IndexBufferをそれぞれ準備します。
IndexBufferの設定では、三角形では頂点indexを使用しないのでNoIndicesを
使います。
四角形では頂点indexを使用しているので、IndexBufferを使います。
描画
target.draw()文を2回使って、三角形と四角形を描画します。
Rust OpenGL gliumライブラリ
今回は、RustでOpenGLを扱うライブラリの一つであるgliumについて
まとめています。(glium([https://github.com/tomaka/glium/)の
examplesにあるtutorial-02.rsを使用しています。)
gliumでは、OpenGLのAPIとは異なる独自のAPIを導入しています。
以下は、gliumでOpenGLを描画する際必要となる文です。
1 windowとOpenGL contextの準備
use glium::{DisplayBuild, Surface}; let display = glium::glutin::WindowBuilder::new() .with_dimensions(800, 600) .with_title(format!("Glium Triangle Test")) .build_glium().unwrap();
window操作のライブラリとして、glutinを利用しています。
この文は、windowとOpenGL contextを生成します。その際、windowサイズ、
windowタイトルも設定しています。
2 vertexの設定
#[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); let vertex1 = Vertex { position: [-0.5, -0.5] }; let vertex2 = Vertex { position: [ 0.0, 0.5] }; let vertex3 = Vertex { position: [ 0.5, -0.5] }; let shape = vec![vertex1, vertex2, vertex3];
#[derive]は継承のアトリビュートです。Vertex structureは、Copy, Clone
トレイトの機能を継承することになります。
頂点座標は、Vertex structureのベクトルとして設定します。
3 VertexBufferの設定
let vertex_buffer = glium::VertexBuffer::new(&display, &shape).unwrap();
頂点座標を、VertexBufferに設定します。
4 IndexBufferの設定
let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);
IndexBufferの設定に相当する文です。
この例では、indexを使用しません。このような場合は、primitive typeを
設定するため、NoIndicesを使います。
5 shaderの設定
let vertex_shader_src = r#" #version 140 in vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } "#; let fragment_shader_src = r#" #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } "#;
6 shderのリンク
let program = glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap();
shaderプログラムのリンクには、Program文を使用します。
最後の引数Noneは、geometry shaderを使用しないことを示しています。
7 windowのクリア、描画、終了
let mut target = display.draw(); target.clear_color(0.0, 0.0, 1.0, 1.0); target.draw(&vertex_buffer, &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default()).unwrap(); target.finish().unwrap();
display.draw()で、描画用フレームバッファ(バックバッファ)を生成します。
target.draw()で、フレームバッファに描画します。その際、VertexBuffer, IndexBuffer,
Programを設定します。
この例では、uniform変数を使用していないので、EmptyUniformsを設定しています。
また、depth、stencil等の描画パラメータも使用していないので、DrawParametersの
設定にはDefaule::default()を設定しています。
target.finish()で、フロントバッファに描画します。
8 windowのクローズ
for ev in display.poll_events() { match ev { glium::glutin::Event::Closed => return, _ => () } }
display.poll_events()で、ウィンドウのイベントリストを生成します。
「glium::glutin::Event::Closed => return」文で、ウィンドウのClosedイベントを
検出するとreturn文を用いて、ループ(loop{})を抜けるようにしています。
Rust glium テッセレーション ( Tessellation )
glium (https://github.com/tomaka/glium)のexamplesに、tessellationの
サンプル(tessellation.rs)があります。
上矢印キーと下矢印キーを使って、tessellation レベルを上げ下げできます。
実行結果
tessellation level = 2
tessellation level = 4
tessellation level = 8
(Inner-levelとOuter-levelは同じ値にしています。)
ビルドと実行
gliumフォルダで
$ cargo run --example tessellation
を実行します。
Rust ImGui + Glium ( OpenGL )
ImGui のGUI(ボタン)から、Gliumで描画したtriangleの回転角をコントロールできる
ようにしています。
(実行結果)
・ imgui ウィンドウ上の「+」ボタンと「ー」ボタンを押すと、回転角の値が増減します。
プログラム
### imgui-glium.rs
#[macro_use] extern crate glium; #[macro_use] extern crate imgui; use glium::glutin; use glium::glutin::{ElementState, Event, MouseButton, MouseScrollDelta, TouchPhase}; use glium::{DisplayBuild, Surface}; use imgui::{ImGui, ImGuiSetCond_FirstUseEver}; use imgui::glium_renderer::Renderer; use std::time::Instant; fn main() { let display = glutin::WindowBuilder::new() .with_dimensions(600, 600) .with_title(format!("ImGui Glium Test")) .build_glium().unwrap(); let mut imgui = ImGui::init(); let mut renderer = Renderer::init(&mut imgui, &display).unwrap(); let mut last_frame = Instant::now(); let mut mouse_pos = (0, 0); let mut mouse_pressed = (false, false, false); let mut mouse_wheel = 0.0; #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); let vertex1 = Vertex { position: [-0.5, -0.5] }; let vertex2 = Vertex { position: [ 0.0, 0.5] }; let vertex3 = Vertex { position: [ 0.5, -0.5] }; let shape = vec![vertex1, vertex2, vertex3]; let vertex_buffer = glium::VertexBuffer::new(&display, &shape).unwrap(); let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList); let vertex_shader_src = r#" #version 140 in vec2 position; uniform mat4 MVP; void main() { gl_Position = MVP * vec4(position, 0.0, 1.0); } "#; let fragment_shader_src = r#" #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } "#; let program = glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap(); let mut t: f32 = 0.0; loop { let mut target = display.draw(); target.clear_color(0.2, 0.2, 0.2, 1.0); let uniform = uniform! { MVP: [ [ t.cos(), t.sin(), 0.0, 0.0], [-t.sin(), t.cos(), 0.0, 0.0], [ 0.0, 0.0, 1.0, 0.0], [ 0.0, 0.0, 0.0, 1.0f32], ], }; target.draw(&vertex_buffer, &indices, &program, &uniform, &Default::default()).unwrap(); let now = Instant::now(); let delta = now - last_frame; let delta_s = delta.as_secs() as f32 + delta.subsec_nanos() as f32 / 1_000_000_000.0; last_frame = now; let scale = imgui.display_framebuffer_scale(); imgui.set_mouse_pos(mouse_pos.0 as f32 / scale.0, mouse_pos.1 as f32 / scale.1); imgui.set_mouse_down(&[mouse_pressed.0, mouse_pressed.1, mouse_pressed.2, false, false]); imgui.set_mouse_wheel(mouse_wheel / scale.1); mouse_wheel = 0.0; let window = display.get_window().unwrap(); let size_points = window.get_inner_size_points().unwrap(); let size_pixels = window.get_inner_size_pixels().unwrap(); let ui = imgui.frame(size_points, size_pixels, delta_s); // imgui ui ui.window(im_str!("Triangle")) .position((10.0, 10.0), ImGuiSetCond_FirstUseEver) .size((200.0, 100.0), ImGuiSetCond_FirstUseEver) .build(|| { ui.text(im_str!("rotation")); ui.separator(); if ui.small_button(im_str!("+")) { t += 0.02; } if ui.small_button(im_str!("-")) { t -= 0.02; } ui.text(im_str!("rotation angle: {:.2} rad", t)); }); renderer.render(&mut target, ui).unwrap(); target.finish().unwrap(); for event in display.poll_events() { match event { Event::Closed => return, Event::MouseMoved(x, y) => mouse_pos = (x, y), Event::MouseInput(state, MouseButton::Left) => mouse_pressed.0 = state == ElementState::Pressed, Event::MouseInput(state, MouseButton::Right) => mouse_pressed.1 = state == ElementState::Pressed, Event::MouseInput(state, MouseButton::Middle) => mouse_pressed.2 = state == ElementState::Pressed, Event::MouseWheel(MouseScrollDelta::LineDelta(_, y), TouchPhase::Moved) => mouse_wheel = y, Event::MouseWheel(MouseScrollDelta::PixelDelta(_, y), TouchPhase::Moved) => mouse_wheel = y, _ => () } } } }
### Cargo.toml
[package] name = "test1" version = "0.1.0" authors = ["xxxxx"] [dependencies] glium = "*" imgui = "*" image = "*"
Rust Glium CubeMap ( OpenGL )
CubeMap
(実行結果)
・ cubemap 画像は、Humus サイト(http://www.humus.name/)のTexures(Yokohama 3)
を使用しています。(画像サイズを512x512にしています。)
プログラム
###glium-cubemap.rs
#[macro_use] extern crate glium; extern crate image; use std::io::Cursor; use glium::{DisplayBuild, Surface}; use glium::glutin; use glium::index::PrimitiveType; mod camera; fn main() { let display = glutin::WindowBuilder::new() .with_vsync() .with_depth_buffer(24) .with_dimensions(800, 600) .with_title(format!("Glium CubeMap")) .build_glium() .unwrap(); let image = image::load(Cursor::new(&include_bytes!("images/posx512.jpg")[..]), image::JPEG).unwrap().to_rgba(); let image_dimensions = image.dimensions(); let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions); let tex_posx = glium::Texture2d::new(&display, image).unwrap(); let image = image::load(Cursor::new(&include_bytes!("images/negx512.jpg")[..]), image::JPEG).unwrap().to_rgba(); let image_dimensions = image.dimensions(); let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions); let tex_negx = glium::Texture2d::new(&display, image).unwrap(); let image = image::load(Cursor::new(&include_bytes!("images/posy512.jpg")[..]), image::JPEG).unwrap().to_rgba(); let image_dimensions = image.dimensions(); let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions); let tex_posy = glium::Texture2d::new(&display, image).unwrap(); let image = image::load(Cursor::new(&include_bytes!("images/negy512.jpg")[..]), image::JPEG).unwrap().to_rgba(); let image_dimensions = image.dimensions(); let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions); let tex_negy = glium::Texture2d::new(&display, image).unwrap(); let image = image::load(Cursor::new(&include_bytes!("images/posz512.jpg")[..]), image::JPEG).unwrap().to_rgba(); let image_dimensions = image.dimensions(); let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions); let tex_posz = glium::Texture2d::new(&display, image).unwrap(); let image = image::load(Cursor::new(&include_bytes!("images/negz512.jpg")[..]), image::JPEG).unwrap().to_rgba(); let image_dimensions = image.dimensions(); let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions); let tex_negz = glium::Texture2d::new(&display, image).unwrap(); let cubemap = glium::texture::Cubemap::empty(&display, 512).unwrap(); // skybox let skybox_vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 3], } implement_vertex!(Vertex, position); let side2: f32 = 50.0 / 2.0; glium::VertexBuffer::new(&display, &[ // Front Vertex { position: [-side2, -side2, side2] }, Vertex { position: [ side2, -side2, side2] }, Vertex { position: [ side2, side2, side2] }, Vertex { position: [-side2, side2, side2] }, // Right Vertex { position: [ side2, -side2, side2] }, Vertex { position: [ side2, -side2, -side2] }, Vertex { position: [ side2, side2, -side2] }, Vertex { position: [ side2, side2, side2] }, // Back Vertex { position: [-side2, -side2, -side2] }, Vertex { position: [-side2, side2, -side2] }, Vertex { position: [ side2, side2, -side2] }, Vertex { position: [ side2, -side2, -side2] }, // Left Vertex { position: [-side2, -side2, side2] }, Vertex { position: [-side2, side2, side2] }, Vertex { position: [-side2, side2, -side2] }, Vertex { position: [-side2, -side2, -side2] }, // Bottom Vertex { position: [-side2, -side2, side2] }, Vertex { position: [-side2, -side2, -side2] }, Vertex { position: [ side2, -side2, -side2] }, Vertex { position: [ side2, -side2, side2] }, // Top Vertex { position: [-side2, side2, side2] }, Vertex { position: [ side2, side2, side2] }, Vertex { position: [ side2, side2, -side2] }, Vertex { position: [-side2, side2, -side2] }, ] ).unwrap() }; let skybox_index_buffer = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, &[ // Front 0u16, 2, 1, 0, 3, 2, // Right 4, 6, 5, 4, 7, 6, // Back 8, 10, 9, 8, 11, 10, // Left 12, 14, 13, 12, 15, 14, // Bottom 16, 18, 17, 16, 19, 18, // Top 20, 22, 21, 20, 23, 22, ]).unwrap(); let skybox_program = glium::Program::from_source(&display, " #version 140 in vec3 position; out vec3 ReflectDir; uniform mat4 model; uniform mat4 view; uniform mat4 perspective; void main() { ReflectDir = position; gl_Position = perspective * view * model * vec4(position, 1.0); } ", " #version 140 in vec3 ReflectDir; out vec4 color; uniform samplerCube cubetex; void main() { color = texture(cubetex, ReflectDir); } ", None).unwrap(); //model let model_vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 3], normal: [f32; 3], } implement_vertex!(Vertex, position, normal); let side2: f32 = 2.0 / 2.0; glium::VertexBuffer::new(&display, &[ // Front Vertex { position: [-side2, -side2, side2], normal: [ 0.0, 0.0, 1.0] }, Vertex { position: [ side2, -side2, side2], normal: [ 0.0, 0.0, 1.0] }, Vertex { position: [ side2, side2, side2], normal: [ 0.0, 0.0, 1.0] }, Vertex { position: [-side2, side2, side2], normal: [ 0.0, 0.0, 1.0] }, // Right Vertex { position: [ side2, -side2, side2], normal: [ 1.0, 0.0, 0.0] }, Vertex { position: [ side2, -side2, -side2], normal: [ 1.0, 0.0, 0.0] }, Vertex { position: [ side2, side2, -side2], normal: [ 1.0, 0.0, 0.0] }, Vertex { position: [ side2, side2, side2], normal: [ 1.0, 0.0, 0.0] }, // Back Vertex { position: [-side2, -side2, -side2], normal: [ 0.0, 0.0, -1.0] }, Vertex { position: [-side2, side2, -side2], normal: [ 0.0, 0.0, -1.0] }, Vertex { position: [ side2, side2, -side2], normal: [ 0.0, 0.0, -1.0] }, Vertex { position: [ side2, -side2, -side2], normal: [ 0.0, 0.0, -1.0] }, // Left Vertex { position: [-side2, -side2, side2], normal: [-1.0, 0.0, 0.0] }, Vertex { position: [-side2, side2, side2], normal: [-1.0, 0.0, 0.0] }, Vertex { position: [-side2, side2, -side2], normal: [-1.0, 0.0, 0.0] }, Vertex { position: [-side2, -side2, -side2], normal: [-1.0, 0.0, 0.0] }, // Bottom Vertex { position: [-side2, -side2, side2], normal: [ 0.0, -1.0, 0.0] }, Vertex { position: [-side2, -side2, -side2], normal: [ 0.0, -1.0, 0.0] }, Vertex { position: [ side2, -side2, -side2], normal: [ 0.0, -1.0, 0.0] }, Vertex { position: [ side2, -side2, side2], normal: [ 0.0, -1.0, 0.0] }, // Top Vertex { position: [-side2, side2, side2], normal: [ 0.0, 1.0, 0.0] }, Vertex { position: [ side2, side2, side2], normal: [ 0.0, 1.0, 0.0] }, Vertex { position: [ side2, side2, -side2], normal: [ 0.0, 1.0, 0.0] }, Vertex { position: [-side2, side2, -side2], normal: [ 0.0, 1.0, 0.0] }, ] ).unwrap() }; let model_index_buffer = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, &[ // Front 0u16, 2, 1, 0, 3, 2, // Right 4, 6, 5, 4, 7, 6, // Back 8, 10, 9, 8, 11, 10, // Left 12, 14, 13, 12, 15, 14, // Bottom 16, 18, 17, 16, 19, 18, // Top 20, 22, 21, 20, 23, 22, ]).unwrap(); let model_program = glium::Program::from_source(&display, " #version 140 in vec3 position; in vec3 normal; out vec4 v_position; out vec3 v_normal; uniform mat4 model; uniform mat4 view; uniform mat4 perspective; void main() { mat4 modelviewMatrix = view * model; mat3 normalMatrix = mat3(modelviewMatrix); v_position = modelviewMatrix * vec4(position, 1.0); v_normal = normalMatrix * normal; gl_Position = perspective * v_position; } ", " #version 140 in vec4 v_position; in vec3 v_normal; out vec4 f_color; uniform samplerCube cubetex; uniform float ReflectFactor; uniform vec4 MaterialColor; uniform vec3 WorldCameraPosition; void main() { vec3 s = normalize(v_normal); vec3 v = normalize(WorldCameraPosition - v_position.xyz); vec3 ReflectDir = reflect(v, s); vec4 cubeMapColor = texture(cubetex, ReflectDir); f_color = mix(MaterialColor, cubeMapColor, ReflectFactor); } ", None).unwrap(); let dest_rect1 = glium::BlitTarget { left: 0, bottom: 0, width: 512, height: 512, }; let mut camera = camera::CameraState::new(); let scale: f32 = 1.0; let scale2: f32 = 1.0; let mut t: f32 = 0.0; // main loop loop { t += 0.002; let framebuffer1 = glium::framebuffer::SimpleFrameBuffer::new(&display, cubemap.main_level().image(glium::texture::CubeLayer::PositiveX)).unwrap(); let framebuffer2 = glium::framebuffer::SimpleFrameBuffer::new(&display, cubemap.main_level().image(glium::texture::CubeLayer::NegativeX)).unwrap(); let framebuffer3 = glium::framebuffer::SimpleFrameBuffer::new(&display, cubemap.main_level().image(glium::texture::CubeLayer::PositiveY)).unwrap(); let framebuffer4 = glium::framebuffer::SimpleFrameBuffer::new(&display, cubemap.main_level().image(glium::texture::CubeLayer::NegativeY)).unwrap(); let framebuffer5 = glium::framebuffer::SimpleFrameBuffer::new(&display, cubemap.main_level().image(glium::texture::CubeLayer::PositiveZ)).unwrap(); let framebuffer6 = glium::framebuffer::SimpleFrameBuffer::new(&display, cubemap.main_level().image(glium::texture::CubeLayer::NegativeZ)).unwrap(); tex_posx.as_surface().blit_whole_color_to(&framebuffer1, &dest_rect1, glium::uniforms::MagnifySamplerFilter::Linear); tex_negx.as_surface().blit_whole_color_to(&framebuffer2, &dest_rect1, glium::uniforms::MagnifySamplerFilter::Linear); tex_negy.as_surface().blit_whole_color_to(&framebuffer3, &dest_rect1, glium::uniforms::MagnifySamplerFilter::Linear); tex_posy.as_surface().blit_whole_color_to(&framebuffer4, &dest_rect1, glium::uniforms::MagnifySamplerFilter::Linear); tex_posz.as_surface().blit_whole_color_to(&framebuffer5, &dest_rect1, glium::uniforms::MagnifySamplerFilter::Linear); tex_negz.as_surface().blit_whole_color_to(&framebuffer6, &dest_rect1, glium::uniforms::MagnifySamplerFilter::Linear); let mut target = display.draw(); target.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0); let model = [ [ t.cos()*scale, 0.0 , t.sin()*scale, 0.0], [ 0.0 , 1.0*scale, 0.0, 0.0], [-t.sin()*scale, 0.0 , t.cos()*scale, 0.0], [ 0.0, 0.0 , 0.0, 1.0f32], ]; let camera_position: [f32; 3]= [0.0, 0.0, -8.0]; camera.set_position((0.0, 0.0, -8.0)); camera.set_direction((0.0, 0.0, 1.0)); let view = camera.get_view(); let perspective = camera.get_perspective(); let material_color: [f32; 4] = [0.9, 0.9, 0.9, 1.0]; let reflect_factor: f32 = 0.9; let skybox_uniforms = uniform! { model: model, view: view, perspective: perspective, cubetex: cubemap.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear), }; let model_uniforms = uniform! { model: [ [ t.cos()*scale2, 0.0 , t.sin()*scale2, 0.0], [ 0.0, 1.0*scale2, 0.0, 0.0], [-t.sin()*scale2, 0.0 , t.cos()*scale2, 0.0], [ 0.0, 0.0 , 0.0, 1.0f32] ], view: view, perspective: perspective, cubetex: cubemap.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear), ReflectFactor: reflect_factor, MaterialColor: material_color, WorldCameraPosition: camera_position, }; let params = glium::DrawParameters { depth: glium::Depth { test: glium::draw_parameters::DepthTest::IfLess, write: true, .. Default::default() }, .. Default::default() }; target.draw(&skybox_vertex_buffer, &skybox_index_buffer, &skybox_program, &skybox_uniforms, ¶ms).unwrap(); target.draw(&model_vertex_buffer, &model_index_buffer, &model_program, &model_uniforms, ¶ms).unwrap(); target.finish().unwrap(); for event in display.poll_events() { match event { glutin::Event::Closed => return, _ => () } } } }
### camera.rs
glium ソース内のexamples/supportのcamera.rsを使用。
###Cargo.toml
[package] name = "cubemap" version = "0.1.0" authors = ["xxxxx"] [dependencies] glium = "*" image = "*" glutin = "*"
Rust glium OpenGL ( triangle )
Rust言語のgliumライブラリ(OpenGLライブラリ)を用いて、coloured triangleを
描画しています。
( 実行結果)
・triangleは、上矢印キー(左回転)と下矢印キー(右回転)を使って回転させて
います。
プログラム
### triangle.rs
#[macro_use]
extern crate glium;
use glium::{DisplayBuild, Surface};
use glium::glutin;
fn main() {
let display = glutin::WindowBuilder::new()
.with_dimensions(600, 600)
.with_title(format!("Glium Triangle Test"))
.build_glium().unwrap();
#[derive(Copy, Clone)]
struct Vertex {
position: [f32; 2],
color: [f32; 3],
}
implement_vertex!(Vertex, position, color);
let vertex1 = Vertex { position: [-0.5, -0.5], color: [0.0, 0.0, 1.0] };
let vertex2 = Vertex { position: [ 0.0, 0.5], color: [0.0, 1.0, 0.0] };
let vertex3 = Vertex { position: [ 0.5, -0.5], color: [1.0, 0.0, 0.0] };
let shape = vec![vertex1, vertex2, vertex3];
let vertex_buffer = glium::VertexBuffer::new(&display, &shape).unwrap();
let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);
let vertex_shader_src = r#"
#version 140
in vec2 position;
in vec3 color;
out vec3 vColor;
uniform mat4 matrix;
void main() {
gl_Position = matrix * vec4(position, 0.0, 1.0);
vColor = color;
}
"#;
let fragment_shader_src = r#"
#version 140
in vec3 vColor;
out vec4 f_color;
void main() {
f_color = vec4(vColor, 1.0);
}
"#;
let program = glium::Program::from_source(&display, vertex_shader_src,
fragment_shader_src, None).unwrap();
let mut t: f32 = 0.0;
loop {
let mut target = display.draw();
target.clear_color(0.0, 0.0, 0.0, 1.0);
let uniforms = uniform! {
matrix: [
[ t.cos(), t.sin(), 0.0, 0.0],
[-t.sin(), t.cos(), 0.0, 0.0],
[ 0.0, 0.0, 1.0, 0.0],
[ 0.0, 0.0, 0.0, 1.0f32],
]
};
target.draw(&vertex_buffer, &indices, &program, &uniforms,
&Default::default()).unwrap();
target.finish().unwrap();
for ev in display.poll_events() {
match ev {
glium::glutin::Event::Closed => return,
glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Up)) => {
t += 0.01;
println!("KeyUP Pressed {}", t);
},
glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _,
Some(glutin::VirtualKeyCode::Down)) => {
t -= 0.01;
println!("KeyDown Pressed {}", t);
},
_ => ()
}
}
}
}
・gliumライブラリのexamplesの例を組み合わせています。
### Cargo.toml
[package]
name = "triangle"
version = "0.1.0"
authors = ["xxxxx"]
[dependencies]
glium = "*"