A Glium 2D back-end for the Piston game engine
pistondevelopers / glium_graphics Goto Github PK
View Code? Open in Web Editor NEWA Glium 2D back-end for the Piston game engine
License: MIT License
A Glium 2D back-end for the Piston game engine
License: MIT License
image
is a large crate which takes a long time to compile and which brings in lots of dependencies.
It should be possible to disable image
using a Cargo feature.
Similarly to #156, I am happy to implement if the PR will be considered.
The previous design did not work well because Glium uses &self
on glium::Context
in combination with some unfortunate left-right evaluation rules in Rust. This leads to a situation where while let
in the event loop borrows the window for the scope of the whole loop, instead of just the right argument:
while let Some(e) = { let mut b = window.borrow_mut(); events.next(&mut *b) } { ... }
(yes, that was the real code! ๐ฑ )
You also had to import Rc
and RefCell
and write two lines to create a window. By implement BuildFromWindowSettings
from the Piston core, this was reduced to one line.
Glium swaps buffers in the drop of glium::Frame
, which means swapping of buffers should be disabled in the Piston event loop. By moving the event loop state inside GliumWindow
, this setting can be turned off by default.
To make glium_graphics work for other backends than Glutin, the OpenGLWindow
trait was required from pistoncore-window. Since we already depended on this in previous design, it was a small step to swap out this dependency with the piston core, which reexports input, window and event_loop.
In most cases, people are using Glutin as window backend. The new design uses Glutin as the default backend. It means you can type GliumWindow
to use Glutin or GliumWindow<Sdl2Window>
to use SDL2 (or another window backend).
The previous design required constructing an GliumGraphics
object to render 2D. The problem was that it borrows a mutable reference to Frame
, which prevents other code to use it in within the same scope. By adding Glium2d::draw
, this moves 2D rendering inside a closure, similarly to opengl_graphics.
With Glutin as the default window backend, shader_version::OpenGL
was reexported to not need depending on Glutin directly.
Old code for image_test example:
extern crate graphics;
extern crate glium;
extern crate glium_graphics;
extern crate image;
extern crate piston;
extern crate glutin_window;
use std::rc::Rc;
use std::cell::RefCell;
use glium::Surface;
use glium_graphics::{
Flip, Glium2d, GliumGraphics, GliumWindow, Texture, TextureSettings
};
use piston::event_loop::*;
use piston::input::RenderEvent;
use piston::window::WindowSettings;
use glutin_window::{ GlutinWindow, OpenGL };
fn main() {
let opengl = OpenGL::V3_2;
let (w, h) = (300, 300);
let ref window: Rc<RefCell<GlutinWindow>> = Rc::new(RefCell::new(
WindowSettings::new("glium_graphics: image_test", [w, h])
.exit_on_esc(true).build().unwrap()
));
let ref mut glium_window = GliumWindow::new(window).unwrap();
let rust_logo = Texture::from_path(glium_window, "assets/rust.png",
Flip::None, &TextureSettings::new()).unwrap();
let mut g2d = Glium2d::new(opengl, glium_window);
let transform = graphics::math::abs_transform(w as f64, h as f64);
let mut events = window.borrow().events().swap_buffers(false);
// Temporary fix for https://github.com/rust-lang/rust/issues/30832.
while let Some(e) = { let mut b = window.borrow_mut(); events.next(&mut *b) } {
use graphics::*;
if let Some(_) = e.render_args() {
let mut target = glium_window.draw();
{
let mut g = GliumGraphics::new(&mut g2d, &mut target);
clear(color::WHITE, &mut g);
rectangle([1.0, 0.0, 0.0, 1.0],
[0.0, 0.0, 100.0, 100.0],
transform,
&mut g);
rectangle([0.0, 1.0, 0.0, 0.3],
[50.0, 50.0, 100.0, 100.0],
transform,
&mut g);
image(&rust_logo, transform.trans(100.0, 100.0), &mut g);
}
target.finish().unwrap();
}
}
}
New code for image_test example:
extern crate graphics;
extern crate glium;
extern crate glium_graphics;
extern crate image;
extern crate piston;
use glium::Surface;
use glium_graphics::{
Flip, Glium2d, GliumWindow, OpenGL, Texture, TextureSettings
};
use piston::input::RenderEvent;
use piston::window::WindowSettings;
fn main() {
let opengl = OpenGL::V3_2;
let (w, h) = (300, 300);
let ref mut window: GliumWindow =
WindowSettings::new("glium_graphics: image_test", [w, h])
.exit_on_esc(true).opengl(opengl).build().unwrap();
let rust_logo = Texture::from_path(window, "assets/rust.png",
Flip::None, &TextureSettings::new()).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);
rectangle([1.0, 0.0, 0.0, 1.0],
[0.0, 0.0, 100.0, 100.0],
c.transform, g);
rectangle([0.0, 1.0, 0.0, 0.3],
[50.0, 50.0, 100.0, 100.0],
c.transform, g);
image(&rust_logo, c.transform.trans(100.0, 100.0), g);
});
target.finish().unwrap();
}
}
}
Output from cargo build --example text_test
:
Compiling pistoncore-glutin_window v0.16.0
/home/wizeman/.cargo/registry/src/github.com-0a35038f75765ae4/pistoncore-glutin_window-0.16.0/src/lib.rs:95:27: 95:53 error: mismatched types:
expected `*const libc::types::common::c95::c_void`,
found `*const ()`
(expected enum `libc::types::common::c95::c_void`,
found ()) [E0308]
/home/wizeman/.cargo/registry/src/github.com-0a35038f75765ae4/pistoncore-glutin_window-0.16.0/src/lib.rs:95 gl::load_with(|s| window.get_proc_address(s));
^~~~~~~~~~~~~~~~~~~~~~~~~~
/home/wizeman/.cargo/registry/src/github.com-0a35038f75765ae4/pistoncore-glutin_window-0.16.0/src/lib.rs:95:27: 95:53 help: run `rustc --explain E0308` to see a detailed explanation
/home/wizeman/.cargo/registry/src/github.com-0a35038f75765ae4/pistoncore-glutin_window-0.16.0/src/lib.rs:223:9: 223:48 error: mismatched types:
expected `*const libc::types::common::c95::c_void`,
found `*const ()`
(expected enum `libc::types::common::c95::c_void`,
found ()) [E0308]
/home/wizeman/.cargo/registry/src/github.com-0a35038f75765ae4/pistoncore-glutin_window-0.16.0/src/lib.rs:223 self.window.get_proc_address(proc_name)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/wizeman/.cargo/registry/src/github.com-0a35038f75765ae4/pistoncore-glutin_window-0.16.0/src/lib.rs:223:9: 223:48 help: run `rustc --explain E0308` to see a detailed explanation
error: aborting due to 2 previous errors
Could not compile `pistoncore-glutin_window`.
To learn more, run the command again with --verbose.
This is to make it more consistent with the other back-ends.
Currently it creates a new vertex buffer at each call.
It also allocates in .collect()
when converting from a flat array to the buffer.
piston_window https://github.com/pistondevelopers/piston_window
Currently, it is a pain to use glium_graphics because of all the stuff to set up. Since we are depending on pistoncore-window anyway to get the OpenGLWindow
trait, we could make GliumWindow
a window wrapper similar to PistonWindow
.
Like this but for glium_graphics:
PistonDevelopers/gfx_graphics#276
I want to do this (seems like the changes can be pretty much mirrored), but thought I'd better post here in case anyone is already working on this or already did it..
Relevant files:
glium_graphics glyph
gfx_graphics glyph
changes
Add #![deny(missing_docs)]
and fill out with some docs.
The Piston Ecosystem has gotten a lot messier since I last checked in. What should be a simple dependency version bump and refactor leads to a downward spiral into madness as every crate in the dependency chain tries to compile a different version of its ancestors.
I just want to bootstrap a game using the latest version of everything, not to have to hunt down or try to figure out a list of crate versions that don't break each other.
I don't know what's going on here but it's a huge barrier to (re)entry.
rustc 1.0.0-nightly (b47aebe3f 2015-02-26) (built 2015-02-26)
$ RUST_BACKTRACE=1 cargo run --example image_test
Running `target/examples/image_test`
thread '<main>' panicked at 'failed to initialize textured shader', /Users/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-mac/build/src/libcore/option.rs:330
stack backtrace:
1: 0x41daac3 - sys::backtrace::write::h0c33dfca8f99823a7hA
2: 0x41efd7e - panicking::on_panic::h63c237d7347b7375J0I
3: 0x41c79f8 - rt::unwind::begin_unwind_inner::h6bff9e2dc073eba1FJI
4: 0x41c820e - rt::unwind::begin_unwind_fmt::hf76b8aeb755b5841iII
5: 0x41ef60e - rust_begin_unwind
6: 0x420f206 - panicking::panic_fmt::h5f34c3efe193c29bY9r
7: 0x40067ff - option::Option<T>::expect::h6139455589386592302
8: 0x3fe6460 - backend::Glium2d::new::hac57dee2683b98815ka
9: 0x3ea4995 - main::hcd2c44beb3bacb19jaa
10: 0x41f1b29 - rust_try_inner
11: 0x41f1b16 - rust_try
12: 0x41f06f3 - rt::lang_start::h5ff98173978cc505pVI
13: 0x3ea6def - main
An unknown error occurred
https://github.com/bvssvni/rust-snake
This game lets you swap between opengl_graphics and gfx_graphics.
This is needed for propagating errors.
I want to make it more similar to the gfx_graphics API for consistency.
DrawTexture
to Texture
Texture::empty
Flip
enumTexture::from_path
Texture::from_image
Texture::from_memory_alpha
Texture::update
See PistonDevelopers/graphics#989
Could copy the "draw_state" example from piston-examples https://github.com/PistonDevelopers/piston-examples/blob/master/src/draw_state.rs and modify it to use glium_graphics.
Docs:
Blending:
Clipping:
Scissors:
Others:
Comments:
RasterMethod::Point
=> PolygonMode::Point
RasterMethod::Line
=> PolygonMode::Line
+ DrawParameters::line_width
RasterMethod::Fill(CullFace)
=> PolygonMode::Fill
+ BackfaceCullingMode
?Both can be put in front of the Glium2d
struct to pack it better.
I'd give more information but I honestly can't even figure out how to do anything with this. There's not exactly much documentation.
These should probably be included in cargo test
so this doesn't happen again.
Is it possible to use this library backend, while still using glium directly to render a 3D game?
Depends on PistonDevelopers/texture#32.
Change Texture
into:
pub struct Texture {
pub texture: Texture2d,
pub min_filter: MinifySamplerFilter,
pub mag_filter: MagnifySamplerFilter,
}
TextureSettings::get_mag
for MagnifySamplerFilter
TextureSettings::get_generate_mipmaps
, TextureSettings::get_min
and TextureSettings::get_mipmap
for MinifySamplerFilter
TextureSettings::get_generate_mipmaps
is true
, call Texture2d::with_mipmapsGraphics::tri_list_uv
, use .sampled() to set .mag_filter
and .min_filter
.Currently the design is as following:
pub struct Texture {
pub texture: Texture2d,
}
This could be changed to:
pub struct Texture(pub Texture2d);
I am using glium_graphics
without any of the functionality from pistoncore-glutin_window
.
It should be possible to remove the dependency on pistoncore-glutin_window
using a Cargo feature.
I am happy to implement if you will consider the PR.
Needs a .travis.yml file
Seems to be a memory leak associated with rendering.
The draw state has been simplified, which requires a different mapping to Glium draw state.
Convert from sRGB to linear color space.
This is to make it more consistent with the other back-ends.
texture::*
at top levelRgba8Texture
for DrawTexture
Can copy code from https://github.com/PistonDevelopers/gfx_texture/blob/master/src/lib.rs#L115-L161
We might want to refactor out this module to its own repo later, and it name collides with the "texture" crate.
Currently, the only GlyphCache
constructor (GlyphCache::new
) takes an AsRef<Path>
as an argument to specify the font. This makes it impossible to construct a GlyphCache
without having the font in its own file on disk. I propose that the GlyphCache
constructor be altered to instead take a Vec<u8>
or a Font
, to allow the user to pass an in-memory font.
BuildFromWindowSettings
hardcodes srgb
to true, but the upstream API settings in Piston has an srgb
flag.
Running from within WSL, I can get the following glium code to render properly through a local X Server.
#[macro_use]
extern crate glium;
fn main() {
use glium::{glutin, Surface};
use glutin::*;
let mut event_loop = glutin::event_loop::EventLoop::new();
let wb = glutin::window::WindowBuilder::new();
let cb = glutin::ContextBuilder::new()
.with_gl(GlRequest::Specific(Api::OpenGl, (3,2)))
.with_srgb(false) // breaks if true
.with_vsync(true); // breaks if false
let display = glium::Display::new(wb, cb, &event_loop).unwrap();
event_loop.run(move |ev, _, control_flow| {
let mut target = display.draw();
target.clear_color(0.0, 0.0, 1.0, 1.0);
target.finish().unwrap();
let next_frame_time = std::time::Instant::now() +
std::time::Duration::from_nanos(16_666_667);
*control_flow = glutin::event_loop::ControlFlow::WaitUntil(next_frame_time);
match ev {
glutin::event::Event::WindowEvent { event, .. } => match event {
glutin::event::WindowEvent::CloseRequested => {
*control_flow = glutin::event_loop::ControlFlow::Exit;
return;
},
_ => return,
},
_ => (),
}
});
}
Some slightly modified code from this library fails to render for me in part because of these lines.
extern crate glium_graphics;
extern crate graphics;
extern crate piston;
use glium_graphics::{Flip, Glium2d, GliumWindow, OpenGL, Texture, TextureSettings};
use piston::event_loop::EventLoop;
use piston::input::RenderEvent;
use piston::window::WindowSettings;
fn main() {
let opengl = OpenGL::V3_2;
let (w, h) = (300, 300);
let ref mut window: GliumWindow = WindowSettings::new("glium_graphics: image_test", [w, h])
.exit_on_esc(true)
.graphics_api(opengl)
.srgb(false)
.vsync(true)
.build()
.unwrap();
let mut g2d = Glium2d::new(opengl, window);
window.set_lazy(true);
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);
rectangle(
[1.0, 0.0, 0.0, 1.0],
[0.0, 0.0, 100.0, 100.0],
c.transform,
g,
);
rectangle(
[0.0, 1.0, 0.0, 0.3],
[50.0, 50.0, 100.0, 100.0],
c.transform,
g,
);
});
target.finish().unwrap();
}
}
}
I'd like to open a PR to resolve this.
There are some .collect::<Vec<_>>()
in there...
rustc 1.0.0-nightly (07560d233 2015-04-20) (built 2015-04-19)
OSX 10.9.5
Currently the Glium textures are wrapped in an Arc
. I did this to conform to the BackEnd
trait, but I think there should be a better way to do this. Possibly the BackEnd
trait leaks the state machine logic through its interface by having methods such as color
, enable_texture
and disable_texture
. This is not necessary for Glium, as it does not expose such state.
Posting notes here to improve the documentation.
Backend
takes &self
in all methodsRc<RefCell<W>>
is used in the Wrapper
struct, which implements Backend
Rc<RefCell<W>>
at startupRc<RefCell<W>>
might have some issues with if let
and while let
expressions. When using GliumWindow::next
, this is not a problem.
OpenGLWindow
trait with these methods(get_proc_address
, is_current
, make_current
) to window
crate -- issue PistonDevelopers/window#44, PR PistonDevelopers/window#45Backend
trait for T: OpenGLWindow
and add fn to create context -- PR #30OpenGLWindow
in window backends:
rustc 1.0.0-nightly (3e4be02b8 2015-03-13) (built 2015-03-13)
src/glyph_cache.rs:28:19: 28:33 error: the trait `glium::texture::Texture2dDataSource<'_>` is not implemented for the type `image::buffer::ImageBuffer<image::color::Luma<u8>, collections::vec::Vec<u8>>` [E0277]
src/glyph_cache.rs:28 let texture = Texture2d::new(
^~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `glium_graphics`.
Use same trick as in gfx_graphics https://github.com/pistondevelopers/gfx_graphics
Should use Glium2d
and GliumGraphics
instead.
Currently unimplemented.
I just realized that this code was apparently never tested. I'm working on fixing it.
shader_version::OpenGL
OpenGL
to Glium2d::new
OpenGL
versionA declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.