[features]
default = []
-no_link_raylib = []
+no_link_libs = []
use std::env;
use std::path::PathBuf;
-#[cfg(not(feature = "no_link_raylib"))]
-fn linking_raylib() {
+#[cfg(not(feature = "no_link_libs"))]
+fn linking_libs() {
println!("cargo:rustc-link-lib=raylib");
+ println!("cargo:rustc-link-lib=OpenGL");
}
-#[cfg(feature = "no_link_raylib")]
-fn linking_raylib() {}
+#[cfg(feature = "no_link_libs")]
+fn linking_libs() {}
fn main() {
- linking_raylib();
+ linking_libs();
println!("cargo:rerun-if-changed=raylib/raylib.h");
let bindings = bindgen::Builder::default()
--- /dev/null
+#version 100
+
+// Default fragment shader used by Raylib.
+
+precision mediump float;
+
+// Input vertex attributes (from vertex shader)
+varying vec2 fragTexCoord;
+varying vec4 fragColor;
+
+// Input uniform values
+uniform sampler2D texture0;
+uniform vec4 colDiffuse;
+
+void main() {
+ // Texel color fetching from texture sampler
+ vec4 texelColor = texture2D(texture0, fragTexCoord);
+
+ gl_FragColor = texelColor*colDiffuse*fragColor;
+}
--- /dev/null
+#version 100
+
+// Input vertex attributes
+attribute vec3 vertexPosition;
+attribute vec2 vertexTexCoord;
+attribute vec4 vertexColor;
+
+// Input uniform values
+uniform mat4 mvp;
+
+// Output vertex attributes (to fragment shader)
+varying vec2 fragTexCoord;
+varying vec4 fragColor;
+
+// custom
+attribute vec2 origin;
+attribute mat3 transform;
+
+void main() {
+ fragTexCoord = vertexTexCoord;
+ fragColor = vertexColor;
+
+ vec3 pos = transform * (vertexPosition - vec3(origin, 0.0)) + vec3(origin, 0.0);
+ gl_Position = mvp * vec4(pos, 1.0);
+}
fn update(&mut self) -> Result<(), String>;
}
+pub trait ShaderInterface {
+ fn set_transform_attrib(&mut self, transform: Transform) -> Result<(), String>;
+ fn set_origin_attrib(&mut self, origin: Vector) -> Result<(), String>;
+ fn begin_draw_shader(&self) -> Result<(), String>;
+ fn end_draw_shader(&self) -> Result<(), String>;
+}
+
pub trait CameraInterface {
fn get_view(&self) -> Result<Rectangle, String>;
fn get_view_xy(&self) -> Result<(f32, f32), String>;
fn load_font(&mut self, path: &Path) -> Result<Box<dyn FontInterface>, String>;
fn load_sound(&mut self, path: &Path) -> Result<Box<dyn SoundInterface>, String>;
fn load_music(&mut self, path: &Path) -> Result<Box<dyn MusicInterface>, String>;
+ fn load_shader(
+ &mut self,
+ name: String,
+ vs: &Path,
+ fs: &Path,
+ ) -> Result<Box<dyn ShaderInterface>, String>;
fn get_camera(&mut self) -> Result<Box<dyn CameraInterface>, String>;
fn get_default_camera(&mut self) -> Result<Box<dyn CameraInterface>, String>;
collections::HashMap,
ffi::CString,
os::raw::{c_char, c_int},
+ path::Path,
rc::Rc,
};
-use crate::faux_quicksilver::Vector;
+use crate::{
+ faux_quicksilver::{Transform, Vector},
+ shaders::{get_attrib_location, set_origin_2f, set_transform_3f},
+};
-use super::{FontInterface, GameInterface, ImageInterface, MusicInterface, SoundInterface};
+use super::{
+ FontInterface, GameInterface, ImageInterface, MusicInterface, ShaderInterface, SoundInterface,
+};
fn fqcolor_to_color(c: crate::faux_quicksilver::Color) -> ffi::Color {
ffi::Color {
ffi::Vector2 { x: v.x, y: v.y }
}
+#[derive(Clone, Debug)]
+pub struct RaylibShader {
+ shader: ffi::Shader,
+}
+
+impl RaylibShader {
+ pub fn get_shader_id(&self) -> ::std::os::raw::c_uint {
+ self.shader.id as ::std::os::raw::c_uint
+ }
+}
+
+#[derive(Clone, Debug)]
+struct RaylibShaderHandler {
+ shader: Rc<RefCell<RaylibShader>>,
+}
+
+impl ShaderInterface for RaylibShaderHandler {
+ fn set_transform_attrib(&mut self, transform: Transform) -> Result<(), String> {
+ let transform_cstr = CString::new("transform")
+ .map_err(|_| String::from("Failed to create \"transform\" CString!"))?;
+ let attr_loc = get_attrib_location(&self.shader.borrow(), &transform_cstr);
+ set_transform_3f(attr_loc, transform);
+ Ok(())
+ }
+
+ fn begin_draw_shader(&self) -> Result<(), String> {
+ unsafe {
+ ffi::BeginShaderMode(self.shader.borrow().shader);
+ }
+ Ok(())
+ }
+
+ fn end_draw_shader(&self) -> Result<(), String> {
+ unsafe {
+ ffi::EndShaderMode();
+ }
+ Ok(())
+ }
+
+ fn set_origin_attrib(&mut self, origin: Vector) -> Result<(), String> {
+ let origin_cstr = CString::new("origin")
+ .map_err(|_| String::from("Failed to create \"origin\" CString!"))?;
+ let attr_loc = get_attrib_location(&self.shader.borrow(), &origin_cstr);
+ set_origin_2f(attr_loc, origin);
+ Ok(())
+ }
+}
+
+impl RaylibShaderHandler {
+ pub fn load_shader(vs: &Path, fs: &Path) -> Result<Self, String> {
+ unsafe {
+ let vs_cstr: CString = CString::from_vec_unchecked(
+ vs.to_str()
+ .ok_or_else(|| format!("Cannot convert path \"{vs:?}\" to str!"))?
+ .as_bytes()
+ .to_owned(),
+ );
+ let fs_cstr: CString = CString::from_vec_unchecked(
+ fs.to_str()
+ .ok_or_else(|| format!("Cannot convert path \"{fs:?}\" to str!"))?
+ .as_bytes()
+ .to_owned(),
+ );
+ Ok(Self {
+ shader: Rc::new(RefCell::new(RaylibShader {
+ shader: ffi::LoadShader(vs_cstr.as_ptr(), fs_cstr.as_ptr()),
+ })),
+ })
+ }
+ }
+}
+
#[derive(Clone, Debug)]
struct RaylibImage {
image: ffi::Image,
fonts: HashMap<String, Rc<RaylibFont>>,
sounds: HashMap<String, Rc<RaylibSound>>,
music: HashMap<String, Rc<RefCell<RaylibMusic>>>,
+ shaders: HashMap<String, Rc<RefCell<RaylibShader>>>,
}
impl RaylibGame {
fonts: HashMap::new(),
sounds: HashMap::new(),
music: HashMap::new(),
+ shaders: HashMap::new(),
})
}
}
impl Drop for RaylibGame {
fn drop(&mut self) {
unsafe {
+ for (_, shader) in &self.shaders {
+ ffi::UnloadShader(shader.borrow().shader);
+ }
for (_, image) in &self.images {
if let Some(texture) = image.borrow_mut().texture.take() {
ffi::UnloadTexture(texture);
}
}
+ fn load_shader(
+ &mut self,
+ name: String,
+ vs: &Path,
+ fs: &Path,
+ ) -> Result<Box<dyn ShaderInterface>, String> {
+ let raylib_shader = RaylibShaderHandler::load_shader(vs, fs)?;
+ self.shaders.insert(name, raylib_shader.shader.clone());
+ Ok(Box::new(raylib_shader))
+ }
+
fn get_camera(&mut self) -> Result<Box<dyn super::CameraInterface>, String> {
todo!()
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Transform {
pub mat: [f32; 9],
- //translate: Vector,
- //rotate: f32,
}
impl Default for Transform {
fn default() -> Self {
Self {
mat: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
- //translate: Vector { x: 0.0, y: 0.0 },
- //rotate: 0.0,
}
}
}
self.mat[6] * rhs.mat[1] + self.mat[7] * rhs.mat[4] + self.mat[8] * rhs.mat[7],
self.mat[6] * rhs.mat[2] + self.mat[7] * rhs.mat[5] + self.mat[8] * rhs.mat[8],
],
- //translate: self.translate + rhs.translate,
- //rotate: self.rotate + rhs.rotate,
}
}
}
0.0,
1.0,
],
- //rotate: rot,
- ..Default::default()
}
}
pub fn translate(x: f32, y: f32) -> Self {
Self {
mat: [1.0, 0.0, x, 0.0, 1.0, y, 0.0, 0.0, 1.0],
- //translate: Vector { x, y },
- ..Default::default()
}
}
-
- //pub fn get_translate(&self) -> Vector {
- // self.translate
- //}
-
- //pub fn get_rotation(&self) -> f32 {
- // self.rotate
- //}
}
pub struct Window {
mod agnostic_interface;
mod faux_quicksilver;
mod original_impl;
+mod shaders;
fn main() {
// TODO
--- /dev/null
+use crate::{
+ agnostic_interface::raylib_impl::RaylibShader,
+ faux_quicksilver::{Transform, Vector},
+};
+use std::ffi::CStr;
+
+extern "C" {
+ pub fn glVertexAttrib2f(index: ::std::os::raw::c_uint, x: f32, y: f32);
+}
+extern "C" {
+ pub fn glVertexAttrib3f(index: ::std::os::raw::c_uint, x: f32, y: f32, z: f32);
+}
+extern "C" {
+ pub fn glVertexAttrib4f(index: ::std::os::raw::c_uint, x: f32, y: f32, z: f32, w: f32);
+}
+extern "C" {
+ pub fn glGetAttribLocation(
+ program: ::std::os::raw::c_uint,
+ name: *const ::std::os::raw::c_char,
+ ) -> ::std::os::raw::c_int;
+}
+
+pub fn get_attrib_location(raylib_shader: &RaylibShader, name: &CStr) -> ::std::os::raw::c_uint {
+ unsafe {
+ glGetAttribLocation(raylib_shader.get_shader_id(), name.as_ptr()) as ::std::os::raw::c_uint
+ }
+}
+
+pub fn set_transform_3f(index: ::std::os::raw::c_uint, transform: Transform) {
+ // OpenGL stores matrix indices in column major order.
+ for idx in index..(index + 3) {
+ unsafe {
+ glVertexAttrib3f(
+ idx,
+ transform.mat[0 + idx as usize],
+ transform.mat[3 + idx as usize],
+ transform.mat[6 + idx as usize],
+ );
+ }
+ }
+}
+
+pub fn set_origin_2f(index: ::std::os::raw::c_uint, origin: Vector) {
+ unsafe {
+ glVertexAttrib2f(index, origin.x, origin.y);
+ }
+}