Setup for drawing with transforms by using shaders
This commit is contained in:
parent
98524fabd7
commit
ad1d2536a3
9 changed files with 209 additions and 26 deletions
|
@ -16,4 +16,4 @@ bindgen = "0.64"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
no_link_raylib = []
|
no_link_libs = []
|
||||||
|
|
11
build.rs
11
build.rs
|
@ -3,16 +3,17 @@ extern crate bindgen;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_link_raylib"))]
|
#[cfg(not(feature = "no_link_libs"))]
|
||||||
fn linking_raylib() {
|
fn linking_libs() {
|
||||||
println!("cargo:rustc-link-lib=raylib");
|
println!("cargo:rustc-link-lib=raylib");
|
||||||
|
println!("cargo:rustc-link-lib=OpenGL");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "no_link_raylib")]
|
#[cfg(feature = "no_link_libs")]
|
||||||
fn linking_raylib() {}
|
fn linking_libs() {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
linking_raylib();
|
linking_libs();
|
||||||
println!("cargo:rerun-if-changed=raylib/raylib.h");
|
println!("cargo:rerun-if-changed=raylib/raylib.h");
|
||||||
|
|
||||||
let bindings = bindgen::Builder::default()
|
let bindings = bindgen::Builder::default()
|
||||||
|
|
20
raylib/simple.fs
Normal file
20
raylib/simple.fs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#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;
|
||||||
|
}
|
25
raylib/transform.vs
Normal file
25
raylib/transform.vs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#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);
|
||||||
|
}
|
|
@ -49,6 +49,13 @@ pub trait MusicInterface {
|
||||||
fn update(&mut self) -> Result<(), String>;
|
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 {
|
pub trait CameraInterface {
|
||||||
fn get_view(&self) -> Result<Rectangle, String>;
|
fn get_view(&self) -> Result<Rectangle, String>;
|
||||||
fn get_view_xy(&self) -> Result<(f32, f32), String>;
|
fn get_view_xy(&self) -> Result<(f32, f32), String>;
|
||||||
|
@ -96,6 +103,12 @@ pub trait GameInterface {
|
||||||
fn load_font(&mut self, path: &Path) -> Result<Box<dyn FontInterface>, 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_sound(&mut self, path: &Path) -> Result<Box<dyn SoundInterface>, String>;
|
||||||
fn load_music(&mut self, path: &Path) -> Result<Box<dyn MusicInterface>, 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_camera(&mut self) -> Result<Box<dyn CameraInterface>, String>;
|
||||||
fn get_default_camera(&mut self) -> Result<Box<dyn CameraInterface>, String>;
|
fn get_default_camera(&mut self) -> Result<Box<dyn CameraInterface>, String>;
|
||||||
|
|
|
@ -12,12 +12,18 @@ use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ffi::CString,
|
ffi::CString,
|
||||||
os::raw::{c_char, c_int},
|
os::raw::{c_char, c_int},
|
||||||
|
path::Path,
|
||||||
rc::Rc,
|
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 {
|
fn fqcolor_to_color(c: crate::faux_quicksilver::Color) -> ffi::Color {
|
||||||
ffi::Color {
|
ffi::Color {
|
||||||
|
@ -41,6 +47,78 @@ fn fqvector_to_vector2(v: crate::faux_quicksilver::Vector) -> ffi::Vector2 {
|
||||||
ffi::Vector2 { x: v.x, y: v.y }
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
struct RaylibImage {
|
struct RaylibImage {
|
||||||
image: ffi::Image,
|
image: ffi::Image,
|
||||||
|
@ -263,6 +341,7 @@ struct RaylibGame {
|
||||||
fonts: HashMap<String, Rc<RaylibFont>>,
|
fonts: HashMap<String, Rc<RaylibFont>>,
|
||||||
sounds: HashMap<String, Rc<RaylibSound>>,
|
sounds: HashMap<String, Rc<RaylibSound>>,
|
||||||
music: HashMap<String, Rc<RefCell<RaylibMusic>>>,
|
music: HashMap<String, Rc<RefCell<RaylibMusic>>>,
|
||||||
|
shaders: HashMap<String, Rc<RefCell<RaylibShader>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RaylibGame {
|
impl RaylibGame {
|
||||||
|
@ -280,6 +359,7 @@ impl RaylibGame {
|
||||||
fonts: HashMap::new(),
|
fonts: HashMap::new(),
|
||||||
sounds: HashMap::new(),
|
sounds: HashMap::new(),
|
||||||
music: HashMap::new(),
|
music: HashMap::new(),
|
||||||
|
shaders: HashMap::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,6 +367,9 @@ impl RaylibGame {
|
||||||
impl Drop for RaylibGame {
|
impl Drop for RaylibGame {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
for (_, shader) in &self.shaders {
|
||||||
|
ffi::UnloadShader(shader.borrow().shader);
|
||||||
|
}
|
||||||
for (_, image) in &self.images {
|
for (_, image) in &self.images {
|
||||||
if let Some(texture) = image.borrow_mut().texture.take() {
|
if let Some(texture) = image.borrow_mut().texture.take() {
|
||||||
ffi::UnloadTexture(texture);
|
ffi::UnloadTexture(texture);
|
||||||
|
@ -528,6 +611,17 @@ impl GameInterface for RaylibGame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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> {
|
fn get_camera(&mut self) -> Result<Box<dyn super::CameraInterface>, String> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,16 +146,12 @@ impl Vector {
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Transform {
|
pub struct Transform {
|
||||||
pub mat: [f32; 9],
|
pub mat: [f32; 9],
|
||||||
//translate: Vector,
|
|
||||||
//rotate: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Transform {
|
impl Default for Transform {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
mat: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
|
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,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,8 +183,6 @@ impl Mul<Transform> for Transform {
|
||||||
self.mat[6] * rhs.mat[1] + self.mat[7] * rhs.mat[4] + self.mat[8] * rhs.mat[7],
|
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],
|
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,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,26 +205,14 @@ impl Transform {
|
||||||
0.0,
|
0.0,
|
||||||
1.0,
|
1.0,
|
||||||
],
|
],
|
||||||
//rotate: rot,
|
|
||||||
..Default::default()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn translate(x: f32, y: f32) -> Self {
|
pub fn translate(x: f32, y: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
mat: [1.0, 0.0, x, 0.0, 1.0, y, 0.0, 0.0, 1.0],
|
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 {
|
pub struct Window {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
mod agnostic_interface;
|
mod agnostic_interface;
|
||||||
mod faux_quicksilver;
|
mod faux_quicksilver;
|
||||||
mod original_impl;
|
mod original_impl;
|
||||||
|
mod shaders;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
47
src/shaders.rs
Normal file
47
src/shaders.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue