#![allow(clippy::single_component_path_imports)]
use gfx; use gfx::*;
use gfx::texture;
use gfx::traits::FactoryExt;
use gfx::Factory;
use ggez::event;
use ggez::graphics;
use ggez::{Context, GameResult};
use glam::*;
use std::env;
use std::f32;
use std::path;
type Isometry3 = Mat4;
type Point3 = Vec3;
type Vector3 = Vec3;
type ColorFormat = gfx::format::Srgba8;
type DepthFormat = gfx::format::DepthStencil;
gfx_defines! {
vertex Vertex {
pos: [f32; 4] = "a_Pos",
tex_coord: [f32; 2] = "a_TexCoord",
}
constant Locals {
transform: [[f32; 4]; 4] = "u_Transform",
rotation: [[f32; 4]; 4] = "u_Rotation",
}
pipeline pipe {
vbuf: gfx::VertexBuffer<Vertex> = (),
transform: gfx::Global<[[f32; 4]; 4]> = "u_Transform",
locals: gfx::ConstantBuffer<Locals> = "Locals",
color: gfx::TextureSampler<[f32; 4]> = "t_Color",
out_color: gfx::RenderTarget<ColorFormat> = "Target0",
out_depth: gfx::DepthTarget<DepthFormat> =
gfx::preset::depth::LESS_EQUAL_WRITE,
}
}
impl Vertex {
fn new(p: [i8; 3], t: [i8; 2]) -> Vertex {
Vertex {
pos: [f32::from(p[0]), f32::from(p[1]), f32::from(p[2]), 1.0],
tex_coord: [f32::from(t[0]), f32::from(t[1])],
}
}
}
fn default_view() -> Isometry3 {
Mat4::look_at_rh(
Point3::new(1.5f32, -5.0, 3.0),
Point3::new(0f32, 0.0, 0.0),
Vector3::Z,
)
}
struct MainState {
frames: usize,
rotation: f32,
data: pipe::Data<gfx_device_gl::Resources>,
pso: gfx::PipelineState<gfx_device_gl::Resources, pipe::Meta>,
slice: gfx::Slice<gfx_device_gl::Resources>,
}
impl MainState {
fn new(ctx: &mut Context) -> Self {
let (factory, _device, _encoder, depth_view, color_view) = graphics::gfx_objects(ctx);
let vs = br#"#version 150 core
in vec4 a_Pos;
in vec2 a_TexCoord;
out vec2 v_TexCoord;
uniform Locals {
mat4 u_Transform;
mat4 u_Rotation;
};
void main() {
v_TexCoord = a_TexCoord;
gl_Position = u_Transform * u_Rotation * a_Pos ;
gl_ClipDistance[0] = 1.0;
}"#;
let fs = br#"#version 150 core
in vec2 v_TexCoord;
out vec4 Target0;
uniform sampler2D t_Color;
void main() {
vec4 tex = texture(t_Color, v_TexCoord);
float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
Target0 = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
}"#;
let vertex_data = [
Vertex::new([-1, -1, 1], [0, 0]),
Vertex::new([1, -1, 1], [1, 0]),
Vertex::new([1, 1, 1], [1, 1]),
Vertex::new([-1, 1, 1], [0, 1]),
Vertex::new([-1, 1, -1], [1, 0]),
Vertex::new([1, 1, -1], [0, 0]),
Vertex::new([1, -1, -1], [0, 1]),
Vertex::new([-1, -1, -1], [1, 1]),
Vertex::new([1, -1, -1], [0, 0]),
Vertex::new([1, 1, -1], [1, 0]),
Vertex::new([1, 1, 1], [1, 1]),
Vertex::new([1, -1, 1], [0, 1]),
Vertex::new([-1, -1, 1], [1, 0]),
Vertex::new([-1, 1, 1], [0, 0]),
Vertex::new([-1, 1, -1], [0, 1]),
Vertex::new([-1, -1, -1], [1, 1]),
Vertex::new([1, 1, -1], [1, 0]),
Vertex::new([-1, 1, -1], [0, 0]),
Vertex::new([-1, 1, 1], [0, 1]),
Vertex::new([1, 1, 1], [1, 1]),
Vertex::new([1, -1, 1], [0, 0]),
Vertex::new([-1, -1, 1], [1, 0]),
Vertex::new([-1, -1, -1], [1, 1]),
Vertex::new([1, -1, -1], [0, 1]),
];
#[rustfmt::skip]
let index_data: &[u16] = &[
0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4, 8, 9, 10, 10, 11, 8, 12, 13, 14, 14, 15, 12, 16, 17, 18, 18, 19, 16, 20, 21, 22, 22, 23, 20, ];
let (vbuf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, index_data);
let texels = [[0x20, 0xA0, 0xC0, 0x00]];
let (_, texture_view) = factory
.create_texture_immutable::<gfx::format::Rgba8>(
texture::Kind::D2(1, 1, texture::AaMode::Single),
texture::Mipmap::Provided,
&[&texels],
)
.unwrap();
let sinfo =
texture::SamplerInfo::new(texture::FilterMethod::Bilinear, texture::WrapMode::Clamp);
let pso = factory.create_pipeline_simple(vs, fs, pipe::new()).unwrap();
let proj = Mat4::perspective_rh(f32::consts::PI / 4.0, 4.0 / 3.0, 1.0, 10.0);
let transform = proj * default_view();
let data = pipe::Data {
vbuf,
transform: transform.to_cols_array_2d(),
locals: factory.create_constant_buffer(1),
color: (texture_view, factory.create_sampler(sinfo)),
out_color: gfx::memory::Typed::new(color_view),
out_depth: gfx::memory::Typed::new(depth_view),
};
MainState {
frames: 0,
data,
pso,
slice,
rotation: 0.0,
}
}
}
impl event::EventHandler<ggez::GameError> for MainState {
fn update(&mut self, _ctx: &mut Context) -> GameResult {
self.rotation += 0.01;
Ok(())
}
fn draw(&mut self, ctx: &mut Context) -> GameResult {
{
let (_factory, device, encoder, _depthview, _colorview) = graphics::gfx_objects(ctx);
encoder.clear(&self.data.out_color, [0.1, 0.1, 0.1, 1.0]);
let rotation = Mat4::from_rotation_z(self.rotation);
let locals = Locals {
transform: self.data.transform,
rotation: rotation.to_cols_array_2d(),
};
encoder.update_constant_buffer(&self.data.locals, &locals);
encoder.clear_depth(&self.data.out_depth, 1.0);
encoder.draw(&self.slice, &self.pso, &self.data);
encoder.flush(device);
}
let dest_point1 = Vec2::new(10.0, 210.0);
let dest_point2 = Vec2::new(10.0, 250.0);
graphics::queue_text(
ctx,
&graphics::Text::new("You can mix ggez and gfx drawing;"),
dest_point1,
None,
);
graphics::queue_text(
ctx,
&graphics::Text::new("it basically draws gfx stuff first, then ggez"),
dest_point2,
None,
);
graphics::draw_queued_text(
ctx,
graphics::DrawParam::default(),
None,
graphics::FilterMode::Linear,
)?;
graphics::present(ctx)?;
self.frames += 1;
if (self.frames % 10) == 0 {
println!("FPS: {}", ggez::timer::fps(ctx));
}
Ok(())
}
}
pub fn main() -> GameResult {
let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
let mut path = path::PathBuf::from(manifest_dir);
path.push("resources");
path
} else {
path::PathBuf::from("./resources")
};
let cb = ggez::ContextBuilder::new("cube", "ggez").add_resource_path(resource_dir);
let (mut ctx, events_loop) = cb.build()?;
let state = MainState::new(&mut ctx);
event::run(ctx, events_loop, state)
}