Parcourir la source

Implemented glc crate with shader module

raster
Bergmann89 il y a 5 ans
Parent
révision
97ab80ea05
11 fichiers modifiés avec 341 ajouts et 9 suppressions
  1. +9
    -0
      Cargo.lock
  2. +4
    -2
      Cargo.toml
  3. +1
    -1
      gl/src/gl.rs
  4. +1
    -0
      gl/src/lib.rs
  5. +9
    -0
      glc/Cargo.toml
  6. +47
    -0
      glc/src/error.rs
  7. +2
    -0
      glc/src/lib.rs
  8. +237
    -0
      glc/src/shader.rs
  9. +3
    -2
      space-crush/Cargo.toml
  10. +20
    -0
      space-crush/src/app.rs
  11. +8
    -4
      space-crush/src/main.rs

+ 9
- 0
Cargo.lock Voir le fichier

@@ -588,6 +588,14 @@ dependencies = [
"xml-rs",
]

[[package]]
name = "glc"
version = "0.1.0"
dependencies = [
"gl",
"thiserror",
]

[[package]]
name = "glutin"
version = "0.25.1"
@@ -1361,6 +1369,7 @@ dependencies = [
"env_logger",
"futures",
"gl",
"glc",
"glutin",
"log",
"num_cpus",


+ 4
- 2
Cargo.toml Voir le fichier

@@ -3,8 +3,9 @@ members = [
"asparit",
"async-ecs",
"async-ecs-derive",
"space-crush",
"gl",
"glc",
"space-crush",
]
default-members = [
"space-crush",
@@ -14,5 +15,6 @@ default-members = [
asparit = { path = "./asparit" }
async-ecs = { path = "./async-ecs" }
async-ecs-derive = { path = "./async-ecs-derive" }
space-crush = { path = "./space-crush" }
gl = { path = "./gl" }
glc = { path = "./glc" }
space-crush = { path = "./space-crush" }

+ 1
- 1
gl/src/gl.rs Voir le fichier

@@ -1,7 +1,7 @@
use std::ops::Deref;
use std::rc::Rc;

use super::bindings::InnerGl;
use super::bindings::{types, Gl as InnerGl};

#[derive(Clone)]
pub struct Gl(Rc<InnerGl>);


+ 1
- 0
gl/src/lib.rs Voir le fichier

@@ -2,6 +2,7 @@ mod bindings;
#[cfg(feature = "generate_struct")]
mod gl;

pub use bindings::types::*;
#[cfg(feature = "generate_struct")]
pub use bindings::Gl as InnerGl;
pub use bindings::*;


+ 9
- 0
glc/Cargo.toml Voir le fichier

@@ -0,0 +1,9 @@
[package]
name = "glc"
version = "0.1.0"
authors = ["Bergmann89 <info@bergmann89.de>"]
edition = "2018"

[dependencies]
gl = { version = "0.1", features = [ "generate_global" ] }
thiserror = "1.0"

+ 47
- 0
glc/src/error.rs Voir le fichier

@@ -0,0 +1,47 @@
use std::io::Error as IoError;
use std::str::Utf8Error;

use thiserror::Error;

#[derive(Debug, Error)]
pub enum Error {
#[error("IO Error: {0}")]
IoError(IoError),

#[error("UTF-8 Error: {0}")]
Utf8Error(Utf8Error),

#[error("OpenGL Error: {0}")]
GlError(gl::GLenum),

#[error("Error while compiling shader object: {0}")]
ShaderCompile(String),

#[error("Error while linking shader program: {0}")]
ShaderLink(String),
}

impl Error {
pub fn err_if<T>(err: &T, value: T) -> Result<T, Error>
where
T: PartialEq<T>,
{
if value.eq(err) {
Err(Error::GlError(gl::get_error()))
} else {
Ok(value)
}
}
}

impl From<IoError> for Error {
fn from(err: IoError) -> Self {
Self::IoError(err)
}
}

impl From<Utf8Error> for Error {
fn from(err: Utf8Error) -> Self {
Self::Utf8Error(err)
}
}

+ 2
- 0
glc/src/lib.rs Voir le fichier

@@ -0,0 +1,2 @@
pub mod error;
pub mod shader;

+ 237
- 0
glc/src/shader.rs Voir le fichier

@@ -0,0 +1,237 @@
use std::fs::read_to_string;
use std::iter::FromIterator;
use std::path::Path;
use std::ptr::{null, null_mut};
use std::str::from_utf8;

use crate::error::Error;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Type {
Vertex,
Compute,
Fragment,
Geometry,
TesslationControl,
TesslationEvaluation,
}

/* Shader */

pub struct Shader {
id: Option<gl::GLuint>,
type_: Type,
source: String,
compiled: bool,
}

impl Shader {
pub fn from_string(type_: Type, source: String) -> Self {
Self {
id: None,
type_,
source,
compiled: false,
}
}

pub fn from_file<P>(type_: Type, path: P) -> Result<Self, Error>
where
P: AsRef<Path>,
{
let source = read_to_string(path)?;

Ok(Self::from_string(type_, source))
}

pub fn id(&mut self) -> Result<gl::GLuint, Error> {
if self.id.is_none() {
let type_ = match self.type_ {
Type::Vertex => gl::VERTEX_SHADER,
Type::Compute => gl::COMPUTE_SHADER,
Type::Fragment => gl::FRAGMENT_SHADER,
Type::Geometry => gl::GEOMETRY_SHADER,
Type::TesslationControl => gl::TESS_CONTROL_SHADER,
Type::TesslationEvaluation => gl::TESS_EVALUATION_SHADER,
};

let id = gl::create_shader(type_);
let id = Error::err_if(&0, id)?;
self.id = Some(id)
}

Ok(self.id.unwrap())
}

pub fn id_opt(&self) -> Option<gl::GLuint> {
self.id
}

pub fn type_(&self) -> Type {
self.type_
}

pub fn compile(&mut self) -> Result<(), Error> {
if self.compiled {
return Ok(());
}

let id = self.id()?;
let source = self.source.as_ptr() as *const i8;
let source: *const *const i8 = &source;

gl::shader_source(id, 1, source, null());
gl::compile_shader(id);

let mut success = 1;
gl::get_shader_iv(id, gl::COMPILE_STATUS, &mut success);

if success != 1 {
let mut len = 0;
gl::get_shader_iv(id, gl::INFO_LOG_LENGTH, &mut len);

let mut buffer = Vec::<u8>::with_capacity(len as usize + 1);
buffer.resize(len as usize, 0);

gl::get_shader_info_log(
id,
len,
null_mut(),
buffer.as_mut_ptr() as *mut gl::types::GLchar,
);

let msg = from_utf8(&buffer)?;

return Err(Error::ShaderCompile(msg.into()));
}

self.compiled = true;

Ok(())
}
}

impl Drop for Shader {
fn drop(&mut self) {
if let Some(id) = &self.id {
gl::delete_shader(*id);
}
}
}

/* Programm */

#[derive(Default)]
pub struct Program {
id: Option<gl::GLuint>,
shaders: Vec<Shader>,
compiled: bool,
}

impl Program {
pub fn id(&mut self) -> Result<gl::GLuint, Error> {
if self.id.is_none() {
let id = gl::create_program();
let id = Error::err_if(&0, id)?;
self.id = Some(id)
}

Ok(self.id.unwrap())
}

pub fn id_opt(&self) -> Option<gl::GLuint> {
self.id
}

pub fn bind(&self) {
if let Some(id) = &self.id {
gl::use_program(*id);
} else {
gl::use_program(0);
}
}

pub fn unbind(&self) {
gl::use_program(0);
}

pub fn link(&mut self, keep_shaders: bool) -> Result<(), Error> {
if self.compiled {
return Ok(());
}

let id = self.id()?;

for shader in &mut self.shaders {
shader.compile()?;
}

for shader in &mut self.shaders {
gl::attach_shader(id, shader.id()?);
}

let mut success = 1;
gl::get_program_iv(id, gl::LINK_STATUS, &mut success);

if success != 1 {
let mut len = 0;
gl::get_program_iv(id, gl::INFO_LOG_LENGTH, &mut len);

let mut buffer = Vec::<u8>::with_capacity(len as usize + 1);
buffer.resize(len as usize, 0);

gl::get_program_info_log(
id,
len,
null_mut(),
buffer.as_mut_ptr() as *mut gl::types::GLchar,
);

let msg = from_utf8(&buffer)?;

return Err(Error::ShaderLink(msg.into()));
}

for shader in &mut self.shaders {
gl::detach_shader(id, shader.id()?);
}

if !keep_shaders {
self.shaders.clear();
}

self.compiled = true;

Ok(())
}
}

impl Extend<Shader> for Program {
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = Shader>,
{
self.shaders.extend(iter);
}
}

impl FromIterator<Shader> for Program {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Shader>,
{
Self {
id: None,
shaders: iter.into_iter().collect(),
compiled: false,
}
}
}

impl Drop for Program {
fn drop(&mut self) {
if let Some(id) = &self.id {
gl::delete_program(*id);
}
}
}

+ 3
- 2
space-crush/Cargo.toml Voir le fichier

@@ -10,9 +10,10 @@ async-ecs = "0.1"
async-ecs-derive = "0.1"
env_logger = "0.8"
futures = "0.3"
gl = { version = "0.1", features = [ "use_log_crate", "generate_global" ] }
gl = { version = "0.1", features = [ "use_log_crate" ] }
glc = "0.1"
glutin = "0.25"
log = { version = "0.4", features = [ "max_level_debug", "release_max_level_warn" ] }
log = { version = "0.4", features = [ "max_level_trace", "release_max_level_warn" ] }
num_cpus = "1.13"
rand = "0.7"
thiserror = "1.0"


+ 20
- 0
space-crush/src/app.rs Voir le fichier

@@ -0,0 +1,20 @@
use async_ecs::World;

pub struct App {
world: World,
}

impl App {
pub fn new() -> Self {
let world = World::default();

Self { world }
}

pub fn progress(&mut self) {
let _world = &mut self.world;

gl::clear_color(0.1, 0.1, 0.1, 1.0);
gl::clear(gl::COLOR_BUFFER_BIT);
}
}

+ 8
- 4
space-crush/src/main.rs Voir le fichier

@@ -1,3 +1,5 @@
mod app;

use std::io::Error as IoError;

use glutin::{
@@ -12,9 +14,11 @@ use log::info;
use thiserror::Error;
use tokio::{runtime::Builder, task::LocalSet};

use app::App;

fn main() -> Result<(), Error> {
env_logger::builder()
.filter_level(log::LevelFilter::Debug)
.filter_level(log::LevelFilter::Trace)
.format_timestamp_nanos()
.init();

@@ -49,9 +53,10 @@ async fn run() -> Result<(), Error> {
));

let context = unsafe { context.make_current().unwrap() };

gl::load_with(|s| context.get_proc_address(s));

let mut run = true;
let mut app = App::new();

loop {
event_loop.run_return(|event, _target, flow_control| {
@@ -76,8 +81,7 @@ async fn run() -> Result<(), Error> {
break;
}

gl::clear_color(0.1, 0.1, 0.1, 1.0);
gl::clear(gl::COLOR_BUFFER_BIT);
app.progress();

context.swap_buffers().unwrap();
}


Chargement…
Annuler
Enregistrer