PistonDevelopers / glium_graphics

A Glium 2D back-end for the Piston game engine
MIT License
17 stars 14 forks source link

Use it within 3D game #129

Closed ruabmbua closed 8 years ago

ruabmbua commented 8 years ago

Is it possible to use this library backend, while still using glium directly to render a 3D game?

gaborigloi commented 8 years ago

Yes, I think so, I've tried using glium + glium_graphics in the past.

This is how I used glium_graphics from glium:

//! Using piston2d-graphics with the piston2d-glium_graphics backend from glium,
//! with a context and window created by glium, to draw lines.

extern crate graphics;
extern crate glium;
extern crate glium_graphics;
extern crate viewport;

use std::thread;
use std::time::Duration;

use glium_graphics::{
    Glium2d, OpenGL
};

fn main() {
    use glium::{DisplayBuild, Surface };
    use glium::backend::Facade;

    let (w, h) = (300_u32, 300_u32);

    // have to specify viewport manually
    let viewport = viewport::Viewport {
        rect: [0, 0, w as i32, h as i32],
        draw_size: [w, h],
        window_size: [w, h]
    };

    let display = glium::glutin::WindowBuilder::new().with_dimensions(w, h).build_glium().unwrap();

    // Obtain version from glium Context
    let opengl = {
        let version = display.get_context().get_opengl_version();
        match (version.1, version.2) {
            (2, 0) => OpenGL::V2_0,
            (2, 1) => OpenGL::V2_1,
            (3, 0) => OpenGL::V3_0,
            (3, 1) => OpenGL::V3_1,
            (3, 2) => OpenGL::V3_2,
            (3, 3) => OpenGL::V3_3,
            (4, 0) => OpenGL::V4_0,
            (4, 1) => OpenGL::V4_1,
            (4, 2) => OpenGL::V4_2,
            (4, 3) => OpenGL::V4_3,
            (4, 4) => OpenGL::V4_4,
            (4, 5) => OpenGL::V4_5,
            _ => {
                panic!("unsupported OpenGL version?: not present in glium_graphics::OpenGL enum");
            }
        }
    };
    let mut g2d = Glium2d::new(opengl, &display);

    // We render a static image in this example, so only refresh when needed, and sleep in the meantime.
    loop {
        for ev in display.poll_events() {
            match ev {
                glium::glutin::Event::Closed => return,
                glium::glutin::Event::Refresh => {
                    let mut target = display.draw();
                    target.clear_color(1.0, 1.0, 1.0, 1.0);
                    g2d.draw(&mut target, viewport, |c, g| {
                        use graphics::*;
                        line([1.0, 0.0, 0.0, 1.0], // the red line
                             2.0,
                             [0.0, 0.0, 100.0, 100.0],
                             c.transform, g);
                    });
                    target.finish().unwrap();
                },
                _ => ()
            }
        }
        thread::sleep(Duration::from_millis(100));
    }
}

I've also tried using glium from piston/glium_graphics:

extern crate graphics;
#[macro_use] extern crate glium;
extern crate glium_graphics;
extern crate piston;

use glium::Surface;
use glium_graphics::{
    Glium2d, GliumWindow, OpenGL
};
use piston::input::RenderEvent;
use piston::window::WindowSettings;

fn main() {
    let opengl = OpenGL::V3_2;
    let (w, h) = (300, 300);
    // GliumWindow implements Facade
    let ref mut window: GliumWindow =
        WindowSettings::new("glium test", [w, h])
        .exit_on_esc(true).opengl(opengl).build().unwrap();

    // ***************** glium code
    #[derive(Copy, Clone)]
    struct Vertex {
        position: [f32; 2],
    }

    implement_vertex!(Vertex, position);
    let shape = {
        let vertex1 = Vertex { position: [-0.5, -0.5] };
        let vertex2 = Vertex { position: [ 0.0,  0.5] };
        let vertex3 = Vertex { position: [ 0.5, -0.25] };
        vec![vertex1, vertex2, vertex3]
    };
    let vertex_buffer = glium::VertexBuffer::new(window, &shape).unwrap();
    let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);
    let vertex_shader_src = include_str!("../shaders/pixel.vert");
    let fragment_shader_src = include_str!("../shaders/green_colour.frag");
    let program = glium::Program::from_source(window, vertex_shader_src, fragment_shader_src, None).unwrap();
    // *********************

    let mut g2d = Glium2d::new(opengl, window);
    while let Some(e) = window.next() {
        use graphics::*;

        if let Some(args) = e.render_args() {
            let mut target = window.draw();
            g2d.draw(&mut target, args.viewport(), |c, g| {
                clear(color::WHITE, g);
                line([1.0, 0.0, 0.0, 1.0], // the red line
                     2.0,
                     [0.0, 0.0, 100.0, 100.0],
                     c.transform, g);
            });
            // glium draw call - we can just use the Surface (Frame) returned by window.draw()
            // It's convenient to use glium from this backend, because, unlike opengl,
            // glium is stateless - we don't have to worry about state changes made by the backend.
            target.draw(&vertex_buffer, &indices, &program, &glium::uniforms::EmptyUniforms,
                &Default::default()).unwrap();
            target.finish().unwrap();
        }

    }
}

Here is the repo with both files and the Cargo.toml: https://github.com/gaborigloi/gium_plus_piston

ruabmbua commented 8 years ago

Thanks for the fast answer. I could not figure it out, cause I am in general a graphics programming newbie.

gaborigloi commented 8 years ago

No problem :), it's quite tricky indeed to use both at the same time.