Vala プログラミング

WebGPU プログラミング

おなが@京都先端科学大

Rust glium ( OpenGL ) triangle and square

rust の glium ライブラリを利用して、三角と四角を同一ウィンドウに
表示します。

実行結果
f:id:onagat12:20170430235917p:plain

プログラム

#[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では、OpenGLAPIとは異なる独自の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 レベルを上げ下げできます。

実行結果
f:id:onagat12:20170424014421p:plain tessellation level = 2
f:id:onagat12:20170424014432p:plain tessellation level = 4
f:id:onagat12:20170424014438p:plain tessellation level = 8
(Inner-levelとOuter-levelは同じ値にしています。)

ビルドと実行
gliumフォルダで
$ cargo run --example tessellation
を実行します。

Rust ImGui + Glium ( OpenGL )

ImGui のGUI(ボタン)から、Gliumで描画したtriangleの回転角をコントロールできる
ようにしています。
f:id:onagat12:20170325183824g:plain
(実行結果)
・ 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

f:id:onagat12:20170325185047g:plain
(実行結果)
・ 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, &params).unwrap();
        target.draw(&model_vertex_buffer, &model_index_buffer, &model_program,
                    &model_uniforms, &params).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を
描画しています。

f:id:onagat12:20170322155548g:plain

( 実行結果)
・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 = "*"