Browse Source

Implemented 'VertexArray'

raster
Bergmann89 4 years ago
parent
commit
384a4f4704
7 changed files with 297 additions and 21 deletions
  1. +14
    -9
      glc/src/array_buffer.rs
  2. +3
    -0
      glc/src/error.rs
  3. +1
    -0
      glc/src/lib.rs
  4. +45
    -0
      glc/src/misc.rs
  5. +14
    -9
      glc/src/shader.rs
  6. +204
    -0
      glc/src/vertex_array.rs
  7. +16
    -3
      space-crush/src/render/background.rs

+ 14
- 9
glc/src/array_buffer.rs View File

@@ -3,7 +3,10 @@ use std::ops::{Deref, DerefMut};
use std::ptr::null;
use std::slice::from_raw_parts_mut;

use crate::{error::Error, misc::AsEnum};
use crate::{
error::Error,
misc::{AsEnum, Bindable},
};

/* ArrayBuffer */

@@ -30,14 +33,6 @@ impl ArrayBuffer {
self.id
}

pub fn bind(&self) {
gl::bind_buffer(self.target.as_enum(), self.id);
}

pub fn unbind(&self) {
gl::bind_buffer(self.target.as_enum(), 0);
}

pub fn buffer_data<T>(&mut self, usage: Usage, data: &[T]) -> Result<(), Error> {
let size = data.len() * size_of::<T>();

@@ -147,6 +142,16 @@ impl ArrayBuffer {
}
}

impl Bindable for ArrayBuffer {
fn bind(&self) {
gl::bind_buffer(self.target.as_enum(), self.id);
}

fn unbind(&self) {
gl::bind_buffer(self.target.as_enum(), 0);
}
}

/* Map */

pub struct Map<'a, T> {


+ 3
- 0
glc/src/error.rs View File

@@ -20,6 +20,9 @@ pub enum Error {
#[error("Error while linking shader program: {0}")]
ShaderLink(String),

#[error("Vertex Array Index is already in use: {0}!")]
VertexArrayIndexAlreadyInUse(gl::GLuint),

#[error("Invalid Parameter!")]
InvalidParameter,
}


+ 1
- 0
glc/src/lib.rs View File

@@ -2,3 +2,4 @@ pub mod array_buffer;
pub mod error;
pub mod misc;
pub mod shader;
pub mod vertex_array;

+ 45
- 0
glc/src/misc.rs View File

@@ -1,3 +1,48 @@
pub trait AsEnum {
fn as_enum(&self) -> gl::GLenum;
}

pub trait Bindable {
fn bind(&self);
fn unbind(&self);
}

pub struct BindGuard<T>
where
T: Bindable,
{
bindable: T,
}

impl<T> BindGuard<T>
where
T: Bindable,
{
pub fn new(bindable: T) -> Self {
bindable.bind();

Self { bindable }
}
}

impl<T> Drop for BindGuard<T>
where
T: Bindable,
{
fn drop(&mut self) {
self.bindable.unbind()
}
}

impl<T> Bindable for &T
where
T: Bindable,
{
fn bind(&self) {
(*self).bind();
}

fn unbind(&self) {
(*self).bind();
}
}

+ 14
- 9
glc/src/shader.rs View File

@@ -3,7 +3,10 @@ use std::path::Path;
use std::ptr::{null, null_mut};
use std::str::from_utf8;

use crate::{error::Error, misc::AsEnum};
use crate::{
error::Error,
misc::{AsEnum, Bindable},
};

/* Programm */

@@ -66,14 +69,6 @@ impl Program {
pub fn id(&self) -> gl::GLuint {
self.id
}

pub fn bind(&self) {
gl::use_program(self.id);
}

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

impl Drop for Program {
@@ -82,6 +77,16 @@ impl Drop for Program {
}
}

impl Bindable for Program {
fn bind(&self) {
gl::use_program(self.id);
}

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

/* Shader */

pub struct Shader {


+ 204
- 0
glc/src/vertex_array.rs View File

@@ -0,0 +1,204 @@
use crate::{
array_buffer::ArrayBuffer,
error::Error,
misc::{AsEnum, BindGuard, Bindable},
};

/* VertexArray */

pub struct VertexArray {
id: gl::GLuint,
buffers: Vec<ArrayBuffer>,
}

impl VertexArray {
pub fn builder() -> Builder {
Builder::default()
}

pub fn buffers(&self) -> &Vec<ArrayBuffer> {
&self.buffers
}

pub fn buffers_mut(&mut self) -> &mut Vec<ArrayBuffer> {
&mut self.buffers
}
}

impl Bindable for VertexArray {
fn bind(&self) {
gl::bind_vertex_array(self.id);
}

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

/* Builder */

#[derive(Default)]
pub struct Builder {
bindings: Vec<Binding>,
}

impl Builder {
pub fn bind_buffer(mut self, buffer: ArrayBuffer) -> BindingBuilder {
let binding = Binding {
buffer,
pointers: Vec::new(),
};

self.bindings.push(binding);

BindingBuilder { builder: self }
}

pub fn build(self) -> Result<VertexArray, Error> {
let mut id = 0;

Error::checked(|| gl::create_vertex_arrays(1, &mut id))?;

let vertex_array = VertexArray {
id,
buffers: Vec::new(),
};

let guard = BindGuard::new(&vertex_array);

for binding in self.bindings {
let _guard = BindGuard::new(&binding.buffer);

for pointer in binding.pointers {
Error::checked(|| {
gl::enable_vertex_attrib_array(pointer.index);
gl::vertex_attrib_pointer(
pointer.index,
pointer.size,
pointer.type_.as_enum(),
if pointer.normalize {
gl::TRUE
} else {
gl::FALSE
},
pointer.stride,
pointer.offset as *const _,
)
})?;
}
}

drop(guard);

Ok(vertex_array)
}
}

/* BindingBuilder */

pub struct BindingBuilder {
builder: Builder,
}

impl BindingBuilder {
pub fn bind_buffer(self, buffer: ArrayBuffer) -> Self {
self.builder.bind_buffer(buffer)
}

pub fn vertex_attrib_pointer(
mut self,
index: gl::GLuint,
size: gl::GLint,
type_: DataType,
normalize: bool,
stride: gl::GLsizei,
offset: gl::GLsizei,
) -> Result<Self, Error> {
for binding in &self.builder.bindings {
for pointer in &binding.pointers {
if pointer.index == index {
return Err(Error::VertexArrayIndexAlreadyInUse(index));
}
}
}

let pointer = Pointer {
index,
size,
type_,
normalize,
stride,
offset,
};

self.builder
.bindings
.last_mut()
.unwrap()
.pointers
.push(pointer);

Ok(self)
}

pub fn build(self) -> Result<VertexArray, Error> {
self.builder.build()
}
}

/* DataType */

#[allow(non_camel_case_types)]
pub enum DataType {
Byte,
UnsignedByte,
Short,
UnsignedShort,
Int,
UnsignedInt,
HalfFloat,
Float,
Double,
Fixed,
Int_2_10_10_10_Rev,
UnsignedInt_2_10_10_10_Rev,
UnsignedInt_10f_11f_11f_Rev,
}

impl AsEnum for DataType {
fn as_enum(&self) -> gl::GLenum {
match self {
Self::Byte => gl::BYTE,
Self::UnsignedByte => gl::UNSIGNED_BYTE,
Self::Short => gl::SHORT,
Self::UnsignedShort => gl::UNSIGNED_SHORT,
Self::Int => gl::INT,
Self::UnsignedInt => gl::UNSIGNED_INT,
Self::HalfFloat => gl::HALF_FLOAT,
Self::Float => gl::FLOAT,
Self::Double => gl::DOUBLE,
Self::Fixed => gl::FIXED,
Self::Int_2_10_10_10_Rev => gl::INT_2_10_10_10_REV,
Self::UnsignedInt_2_10_10_10_Rev => gl::UNSIGNED_INT_2_10_10_10_REV,
Self::UnsignedInt_10f_11f_11f_Rev => gl::UNSIGNED_INT_10F_11F_11F_REV,
}
}
}

/* Binding */

struct Binding {
buffer: ArrayBuffer,
pointers: Vec<Pointer>,
}

/* Pointer */

struct Pointer {
index: gl::GLuint,
size: gl::GLint,
type_: DataType,
normalize: bool,
stride: gl::GLsizei,
offset: gl::GLsizei,
}

+ 16
- 3
space-crush/src/render/background.rs View File

@@ -4,13 +4,14 @@ use async_ecs::System;
use glc::{
array_buffer::{ArrayBuffer, Target, Usage},
shader::{Program, Shader, Type},
vertex_array::{DataType, VertexArray},
};

use crate::Error;

pub struct Background {
program: Program,
array_buffer: ArrayBuffer,
vertex_array: VertexArray,
}

impl Background {
@@ -53,9 +54,21 @@ impl Background {
};
}

const STRIDE_POS: gl::GLsizei = size_of::<Vertex>() as gl::GLsizei;
const STRIDE_TEX: gl::GLsizei = size_of::<Vertex>() as gl::GLsizei;

const OFFSET_POS: gl::GLsizei = 0;
const OFFSET_TEX: gl::GLsizei = 2 * size_of::<f32>() as gl::GLsizei;

let vertex_array = VertexArray::builder()
.bind_buffer(array_buffer)
.vertex_attrib_pointer(0, 2, DataType::Float, false, STRIDE_POS, OFFSET_POS)?
.vertex_attrib_pointer(1, 2, DataType::Float, false, STRIDE_TEX, OFFSET_TEX)?
.build()?;

Ok(Self {
program,
array_buffer,
vertex_array,
})
}
}
@@ -65,7 +78,7 @@ impl<'a> System<'a> for Background {

fn run(&mut self, (): Self::SystemData) {
let _program = &self.program;
let _array_buffer = &self.array_buffer;
let _vertex_array = &self.vertex_array;

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


Loading…
Cancel
Save