use std140_data::Data;
use super::components::ProgramRef;
use rin_material::{
texture::{TextureSampler, CubemapSampler},
AlphaType,
Property,
Face,
MaterialParameterTypes,
BlendFactor,
UniformValueRef,
UniformRef,
};
use std::path::PathBuf;
#[cfg(glsl_debug)]
use std::path::Path;
use std::hash::Hasher;
use rin_gl as gl;
use rin_gl::{Shader, program::UniformValue};
use rinecs::{EntitiesThreadLocal, ResourcesThreadLocal};
use std::hash::Hash;
use std::fmt;
use rin_gl::types::*;
use super::components::RenderPlane;
use glin::OffscreenBuffer;
use std::iter::FromIterator;
use downcast_rs::Downcast;
use rin_graphics::CameraExt;
use rin_math::Angle;
pub use texture_pool::{TexturesPool, Image};
pub use shader_material::{ShaderMaterial, ShaderMaterialBuilder};
pub use postfragment_material::{PostFragmentMaterial, PostFragmentMaterialBuilder};
pub use material_pool::{
MaterialPool, MaterialCache, ShadowMaterialPool, ShadowMaterialCache, MaterialData,
material_pool_updater, material_offsets_updater,
shadow_material_pool_updater, shadow_material_offsets_updater,
UnifiedMaterialOffset, PerMaterialOffset, Buffer,
};
pub use program_cache::{ProgramCache, program_cache_updater};
pub use std140_data;
#[macro_use] mod macros;
#[macro_use] mod shader_material;
#[macro_use] mod postfragment_material;
mod basic_material;
mod outline_material;
mod pbr_material;
mod skybox;
mod texture_pool;
mod material_pool;
mod program_cache;
#[cfg(image_enabled)]
pub mod water;
fn into_gl_face(face: Face) -> GLenum{
match face{
Face::Front => gl::FRONT,
Face::Back => gl::BACK,
}
}
#[cfg(not(any(feature="gles", feature="webgl")))]
pub(crate) fn into_gl_property(property: &Property) -> glin::Property{
match property{
Property::ClipDistance(clip_dist) => glin::Property::ClipDistance(clip_dist.clone()) ,
Property::CullFace(face) => glin::Property::CullFace(face.map(|f| into_gl_face(f))),
Property::FrontFace(face) => glin::Property::FrontFace(into_gl_face(*face)),
Property::DepthClamp(v) => glin::Property::DepthClamp(*v),
Property::DepthTest(v) => glin::Property::DepthTest(*v),
Property::Dither(v) => glin::Property::Dither(*v),
Property::LineSmooth(v) => glin::Property::LineSmooth(*v),
Property::Multisample(v) => glin::Property::Multisample(*v),
Property::PolygonOffsetFill(v) => glin::Property::PolygonOffsetFill(*v),
Property::PolygonOffsetLine(v) => glin::Property::PolygonOffsetLine(*v),
Property::PolygonOffsetPoint(v) => glin::Property::PolygonOffsetPoint(*v),
Property::PolygonSmooth(v) => glin::Property::PolygonSmooth(*v),
Property::RasterizerDiscard(v) => glin::Property::RasterizerDiscard(*v),
Property::StencilMask(v) => glin::Property::StencilMask(*v),
Property::Scissor(v) => glin::Property::Scissor(v.map(|v| glin::Rect{
bottom: v.pos.y, left: v.pos.x, width: v.width, height: v.height
})),
Property::StencilTest(v) => glin::Property::StencilTest(*v),
Property::TextureCubemapSeamless(v) => glin::Property::TextureCubemapSeamless(*v),
Property::DepthMask(v) => glin::Property::DepthMask(*v),
Property::ColorMask(r,g,b,a) => glin::Property::ColorMask([*r,*g,*b,*a]),
Property::DepthRange(v1, v2) => glin::Property::DepthRange(*v1, *v2),
Property::LineWidth(v) => glin::Property::LineWidth(*v),
Property::PointSize(v) => glin::Property::PointSize(*v),
Property::ProgramPointSize(v) => glin::Property::ProgramPointSize(*v),
}
}
#[cfg(any(feature="gles", feature="webgl"))]
pub(crate) fn into_gl_property(property: &Property) -> glin::Property{
match property{
Property::ClipDistance(clip_dist) => unimplemented!() ,
Property::CullFace(face) => glin::Property::CullFace(face.map(|f| into_gl_face(f))),
Property::FrontFace(face) => glin::Property::FrontFace(into_gl_face(*face)),
Property::DepthClamp(v) => unimplemented!(),
Property::DepthTest(v) => glin::Property::DepthTest(*v),
Property::Dither(v) => glin::Property::Dither(*v),
Property::LineSmooth(v) => unimplemented!(),
Property::Multisample(v) => unimplemented!(),
Property::PolygonOffsetFill(v) => glin::Property::PolygonOffsetFill(*v),
Property::PolygonOffsetLine(v) => unimplemented!(),
Property::PolygonOffsetPoint(v) => unimplemented!(),
Property::PolygonSmooth(v) => unimplemented!(),
Property::RasterizerDiscard(v) => glin::Property::RasterizerDiscard(*v),
Property::StencilMask(v) => glin::Property::StencilMask(*v),
Property::Scissor(v) => glin::Property::Scissor(v.map(|v| glin::Rect{
bottom: v.pos.y, left: v.pos.x, width: v.width, height: v.height
})),
Property::StencilTest(v) => glin::Property::StencilTest(*v),
Property::TextureCubemapSeamless(v) => unimplemented!(),
Property::DepthMask(v) => glin::Property::DepthMask(*v),
Property::ColorMask(r,g,b,a) => glin::Property::ColorMask([*r,*g,*b,*a]),
Property::DepthRange(v1, v2) => glin::Property::DepthRange(*v1, *v2),
Property::LineWidth(v) => glin::Property::LineWidth(*v),
Property::PointSize(v) => unimplemented!(),
Property::ProgramPointSize(v) => unimplemented!(),
}
}
pub trait ToGlinShaderPrecision{
fn to_glin(self) -> glin::program::ShaderPrecision;
}
impl ToGlinShaderPrecision for rin_material::ShaderPrecision{
fn to_glin(self) -> glin::program::ShaderPrecision{
match self{
Self::Low => glin::program::ShaderPrecision::Low,
Self::Medium => glin::program::ShaderPrecision::Medium,
Self::High => glin::program::ShaderPrecision::High,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum PostFragment{
Path{
path: PathBuf,
replacements: Vec<(String, String)>,
base_path: Option<PathBuf>,
includes: Vec<(String, String)>,
},
Source{
include_name: String,
source: String,
replacements: Vec<(String, String)>,
base_path: Option<PathBuf>,
includes: Vec<(String, String)>,
},
}
#[macro_export]
#[cfg(glsl_debug)]
macro_rules! post_fragment {
($path: expr, $replacements: expr) => {{
let path = ::std::path::Path::new($path);
let base_path = if path.is_absolute(){
path.parent()
}else{
::std::path::Path::new(file!()).parent()
};
$crate::renderer::PostFragment::Path{
path: path.to_owned(),
replacements: $replacements,
base_path: base_path.map(|p| p.to_owned()),
includes: Vec::new(),
}
}};
($path: expr) => {{
$crate::post_fragment!($path, vec![])
}};
}
#[macro_export]
#[cfg(not(glsl_debug))]
macro_rules! post_fragment {
($path: expr, $replacements: expr) => {{
let path = ::std::path::Path::new($path);
let base_path = if path.is_absolute(){
path.parent()
}else{
::std::path::Path::new(file!()).parent()
};
$crate::renderer::PostFragment::Source{
include_name: $path.to_owned(),
source: include_str!($path).to_owned(),
replacements: $replacements,
base_path: base_path.map(|p| p.to_owned()),
includes: Vec::new(),
}
}};
($path: expr) => {{
$crate::post_fragment!($path, vec![])
}};
}
#[macro_export]
macro_rules! post_fragment_source {
($source: expr) => {{
let include_name = format!("post fragment inlined in {}:{}:{}", file!(), line!(), column!());
$crate::renderer::PostFragment::Source{
include_name,
source: $source.to_owned(),
replacements: vec![],
base_path: None,
includes: Vec::new(),
}
}};
}
#[derive(Clone)]
pub struct ProgramSettings{
pub version: usize,
pub extensions: Vec<String>,
pub precision: glin::program::ShaderPrecision,
pub defines: Vec<(String, String)>,
pub includes_replace: Vec<(String, String)>,
pub bindings: rin_gl::HashMap<String, u32>,
}
impl Default for ProgramSettings{
fn default() -> ProgramSettings{
ProgramSettings{
version: super::default_glsl_version(),
extensions: vec![],
precision: glin::program::ShaderPrecision::High,
defines: vec![],
includes_replace: vec![],
bindings: super::default_attribute_bindings(),
}
}
}
pub struct RenderPlaneAsUniform<'a>{
pub color: Option<&'a str>,
pub depth: Option<&'a str>,
}
#[derive(Clone, Copy, Debug)]
pub struct MaterialTransparency{
pub alpha_type: AlphaType,
pub is_translucent: bool,
pub is_visible: bool,
pub priority: Option<i32>,
}
impl Default for MaterialTransparency{
fn default() -> MaterialTransparency{
MaterialTransparency {
alpha_type: AlphaType::None,
is_translucent: false,
is_visible: true,
priority: None,
}
}
}
#[derive(Clone)]
pub enum PropertyChanged<T>{
Always(T),
New(T),
Old,
}
impl<T: fmt::Debug> fmt::Debug for PropertyChanged<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PropertyChanged::Always(t) => f.debug_tuple("Always").field(t).finish(),
PropertyChanged::New(t) => f.debug_tuple("New").field(t).finish(),
PropertyChanged::Old => f.debug_tuple("Old").finish(),
}
}
}
impl<T> FromIterator<T> for PropertyChanged<T>{
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> PropertyChanged<T>{
if let Some(last) = iter.into_iter().next() {
PropertyChanged::New(last)
}else{
PropertyChanged::Old
}
}
}
impl<T> PropertyChanged<T>{
pub fn is_new(&self) -> bool {
match self{
PropertyChanged::Always(_) | PropertyChanged::Old => false,
PropertyChanged::New(_) => true
}
}
pub fn is_old(&self) -> bool {
match self{
PropertyChanged::Always(_) | PropertyChanged::New(_) => false,
PropertyChanged::Old => true
}
}
pub fn is_always(&self) -> bool {
match self{
PropertyChanged::Old | PropertyChanged::New(_) => false,
PropertyChanged::Always(_) => true
}
}
pub fn unwrap(self) -> T {
match self{
PropertyChanged::Always(t) | PropertyChanged::New(t) => t,
PropertyChanged::Old => panic!("Trying to unwrap property that didn't change")
}
}
pub fn unwrap_or(self, default: T) -> T{
match self{
PropertyChanged::Always(t) | PropertyChanged::New(t) => t,
PropertyChanged::Old => default
}
}
pub fn unwrap_or_else<F>(self, default: F) -> T
where F: FnOnce() -> T
{
match self{
PropertyChanged::Always(t) | PropertyChanged::New(t) => t,
PropertyChanged::Old => default()
}
}
pub fn expect(self, msg: &str) -> T{
match self{
PropertyChanged::Always(t) | PropertyChanged::New(t) => t,
PropertyChanged::Old => panic!("{}", msg)
}
}
pub fn map<F,U>(self, f: F) -> PropertyChanged<U>
where F: FnOnce(T) -> U
{
match self{
PropertyChanged::New(t) => PropertyChanged::New(f(t)),
PropertyChanged::Always(t) => PropertyChanged::Always(f(t)),
PropertyChanged::Old => PropertyChanged::Old,
}
}
pub fn as_ref(&self) -> PropertyChanged<&T>{
match self{
PropertyChanged::New(t) => PropertyChanged::New(&t),
PropertyChanged::Always(t) => PropertyChanged::Always(&t),
PropertyChanged::Old => PropertyChanged::Old,
}
}
}
impl<T: Clone> PropertyChanged<&T>{
pub fn cloned(self) -> PropertyChanged<T>{
match self{
PropertyChanged::New(t) => PropertyChanged::New(t.clone()),
PropertyChanged::Always(t) => PropertyChanged::Always(t.clone()),
PropertyChanged::Old => PropertyChanged::Old,
}
}
}
impl<T> Default for PropertyChanged<T>{
fn default() -> PropertyChanged<T>{
PropertyChanged::Old
}
}
pub trait Material: rin_material::Material + MaterialParameterTypes + std140_data::WriteStd140{
fn shaders(&self) -> PropertyChanged<Vec<Shader>>;
fn data(&self) -> PropertyChanged<Option<Data>> {
if self.has_data() {
if self.any_data_changed() {
let mut data = Data::new();
self.write_std140(&mut data);
PropertyChanged::New(Some(data))
}else{
PropertyChanged::Old
}
}else{
PropertyChanged::Always(None)
}
}
fn transparency(&self) -> PropertyChanged<MaterialTransparency>{
if let Some(alpha_type) = self.alpha_type_parameter(){
if alpha_type.has_changed(){
PropertyChanged::New(MaterialTransparency{
alpha_type: **alpha_type,
is_translucent: **alpha_type == AlphaType::Blending,
is_visible: true,
priority: None,
})
}else{
PropertyChanged::Old
}
}else{
PropertyChanged::Always(MaterialTransparency{
alpha_type: AlphaType::None,
is_translucent: false,
is_visible: true,
priority: None,
})
}
}
fn uniforms(&self) -> PropertyChanged<Vec<glin::program::Uniform>>{
if self.has_uniforms() {
if self.any_uniform_changed() {
let uniforms = self.uniform_parameters()
.iter()
.filter(|u| u.is_some())
.map(|u| glin::program::uniform(u.name(), &u.as_uniform_value()))
.collect();
PropertyChanged::New(uniforms)
}else{
PropertyChanged::Old
}
}else{
PropertyChanged::Always(vec![])
}
}
fn textures(&self) -> PropertyChanged<Vec<(&str, TextureSampler)>>{
if self.has_textures() {
if self.any_texture_changed() {
let textures = self.texture_parameters().into_iter()
.filter_map(|p| p.texture().map(|t| (p.name(), t)))
.collect();
PropertyChanged::New(textures)
}else{
PropertyChanged::Old
}
}else{
PropertyChanged::Always(vec![])
}
}
fn cubemaps(&self) -> PropertyChanged<Vec<(&str, CubemapSampler)>>{
if self.has_cubemaps() {
if self.any_cubemap_changed() {
let cubemaps = self.cubemap_parameters().into_iter()
.filter_map(|p| p.cubemap().map(|t| (p.name(), t)))
.collect();
PropertyChanged::New(cubemaps)
}else{
PropertyChanged::Old
}
}else{
PropertyChanged::Always(vec![])
}
}
fn render_planes(&self) -> PropertyChanged<Option<(rinecs::Entity, &[RenderPlaneAsUniform])>>{
PropertyChanged::Always(None)
}
fn properties(&self) -> PropertyChanged<Vec<glin::Property>>{
if let Some(p) = self.properties_parameter(){
if p.has_changed() {
PropertyChanged::New(p.iter().map(|p| into_gl_property(p)).collect())
}else{
PropertyChanged::Old
}
}else{
PropertyChanged::Always(vec![])
}
}
fn program_settings(&self) -> PropertyChanged<ProgramSettings>{
PropertyChanged::Always(ProgramSettings::default())
}
fn update(&mut self, _: EntitiesThreadLocal, _: ResourcesThreadLocal){}
}
pub trait FullMaterial: rin_material::Material + Downcast {
fn post_fragment(&self) -> PropertyChanged<Option<&PostFragment>>;
fn full_uniforms(&mut self) -> PropertyChanged<Vec<glin::program::Uniform>>;
fn full_textures(&self,
textures_pool: &TexturesPool,
texture_offset: &mut u32) -> PropertyChanged<(Vec<glin::program::Uniform>, u64)>;
fn full_cubemaps(&self,
textures_pool: &TexturesPool,
texture_offset: &mut u32) -> PropertyChanged<(Vec<glin::program::Uniform>, u64)>;
fn full_renderplanes(&self,
entities: &EntitiesThreadLocal,
texture_offset: u32) -> PropertyChanged<Option<(Vec<glin::program::Uniform>, u64)>>;
fn full_reset_changed(&mut self);
fn material(&self) -> &dyn Material;
fn material_mut(&mut self) -> &mut dyn Material;
}
downcast_rs::impl_downcast!(FullMaterial);
impl<M: Material + 'static> FullMaterial for M {
#[inline]
fn post_fragment(&self) -> PropertyChanged<Option<&PostFragment>>{
PropertyChanged::Always(None)
}
#[inline]
fn full_uniforms(&mut self) -> PropertyChanged<Vec<glin::program::Uniform>>{
self.uniforms()
}
#[inline]
fn full_textures(&self,
textures_pool: &TexturesPool,
texture_offset: &mut u32) -> PropertyChanged<(Vec<glin::program::Uniform>, u64)>
{
self.textures().map(|textures| {
let mut hasher = fxhash::FxHasher::default();
let textures = textures.iter().map(|(name, tex)| {
tex.hash(&mut hasher);
let texture = &textures_pool[tex.texture];
let uniform = if let Some(sampler) = tex.sampler.map(|s| &textures_pool[s]){
let sampler = texture.texture_sampler(sampler);
glin::program::uniform(name, &(sampler, *texture_offset))
}else{
glin::program::uniform(name, &(texture, *texture_offset))
};
*texture_offset += 1;
uniform
}).collect();
(textures, hasher.finish())
})
}
#[inline]
fn full_cubemaps(&self,
textures_pool: &TexturesPool,
texture_offset: &mut u32) -> PropertyChanged<(Vec<glin::program::Uniform>, u64)>
{
self.cubemaps().map(|cubemaps| {
let mut hasher = fxhash::FxHasher::default();
let cubemaps = cubemaps.iter().map(|(name, cm)| {
cm.hash(&mut hasher);
let cubemap = &textures_pool[cm.cubemap];
let uniform = if let Some(sampler) = cm.sampler.map(|s| &textures_pool[s]){
let sampler = cubemap.cubemap_sampler(sampler);
glin::program::uniform(name, &(sampler, *texture_offset))
}else{
glin::program::uniform(name, &(cubemap, *texture_offset))
};
*texture_offset += 1;
uniform
}).collect();
(cubemaps, hasher.finish())
})
}
#[inline]
fn full_renderplanes(&self,
entities: &EntitiesThreadLocal,
mut texture_offset: u32) -> PropertyChanged<Option<(Vec<glin::program::Uniform>, u64)>>
{
self.render_planes().map(|renderplanes| if let Some((entity, uniforms)) = renderplanes {
let mut hasher = fxhash::FxHasher::default();
let hasher_ref = &mut hasher;
let renderplanes = entities.component_for::<RenderPlane>(&entity).unwrap();
let renderplanes = renderplanes.into_iter().zip(uniforms.iter())
.flat_map(move |(renderplane, uniform)|
{
let color = uniform.color.map(|name| {
let texture = renderplane.render_buffer().color_tex(0).unwrap();
texture.id().hash(hasher_ref);
let location = texture_offset;
texture_offset += 1;
if let Some(sampler) = renderplane.render_sampler.as_ref(){
let texture_sampler = texture.texture_sampler(sampler);
glin::program::uniform(name, &(texture_sampler, location))
}else{
glin::program::uniform(name, &(texture, location))
}
});
let depth = uniform.depth.map(|name| {
let texture = renderplane.render_buffer().depth_tex().unwrap();
texture.id().hash(hasher_ref);
let location = texture_offset;
texture_offset += 1;
if let Some(sampler) = renderplane.render_sampler.as_ref(){
let texture_sampler = texture.texture_sampler(sampler);
glin::program::uniform(name, &(texture_sampler, location))
}else{
glin::program::uniform(name, &(texture, location))
}
});
color.into_iter().chain(depth)
}).collect();
Some((renderplanes, hasher.finish()))
}else{
None
})
}
#[inline]
fn material(&self) -> &dyn Material{
self
}
#[inline]
fn material_mut(&mut self) -> &mut dyn Material{
self
}
#[inline]
fn full_reset_changed(&mut self){
self.reset_changed()
}
}
pub struct Materials;
pub struct MaterialOffsets{
offsets_data: Vec<u32>,
offsets_buffer: glin::SharedBuffer<u32>,
}
impl MaterialOffsets{
pub fn buffer(&self) -> &glin::SharedBuffer<u32>{
&self.offsets_buffer
}
fn load_data(&mut self){
self.offsets_buffer.load(&self.offsets_data, gl::STATIC_DRAW);
}
}
pub struct ShadowMaterialOffsets{
all_offsets_data: Vec<u32>,
dynamic_offsets_data: Vec<u32>,
static_offsets_data: Vec<u32>,
all_offsets_buffer: Option<glin::SharedBuffer<u32>>,
dynamic_offsets_buffer: Option<glin::SharedBuffer<u32>>,
static_offsets_buffer: Option<glin::SharedBuffer<u32>>,
}
impl ShadowMaterialOffsets{
pub fn all_buffer(&self) -> Option<&glin::SharedBuffer<u32>>{
self.all_offsets_buffer.as_ref()
}
pub fn dynamic_buffer(&self) -> Option<&glin::SharedBuffer<u32>>{
self.dynamic_offsets_buffer.as_ref()
}
pub fn static_buffer(&self) -> Option<&glin::SharedBuffer<u32>>{
self.static_offsets_buffer.as_ref()
}
fn load_dynamic_data(&mut self){
if let Some(dynamic_offsets_buffer) = self.dynamic_offsets_buffer.as_mut(){
dynamic_offsets_buffer.load(&self.dynamic_offsets_data, gl::STATIC_DRAW);
}
}
fn load_static_data(&mut self){
if let Some(static_offsets_buffer) = self.static_offsets_buffer.as_mut(){
static_offsets_buffer.load(&self.static_offsets_data, gl::STATIC_DRAW);
}
}
fn load_all_data(&mut self){
if let Some(all_offsets_buffer) = self.all_offsets_buffer.as_mut(){
all_offsets_buffer.load(&self.all_offsets_data, gl::STATIC_DRAW);
}
}
}
bitflags::bitflags!{
pub struct CameraType: u32{
const ORTHOGRAPHIC = 2;
const FAR_AT_INFINITY = 4;
const REVERSED_Z = 8;
}
}
impl CameraType {
fn from_camera(camera: &dyn CameraExt) -> CameraType {
let mut ty = CameraType::empty();
if camera.fov().is_none() {
ty.insert(CameraType::ORTHOGRAPHIC)
}
if camera.far_at_infinity(){
ty.insert(CameraType::FAR_AT_INFINITY)
}
if camera.reversed_z(){
ty.insert(CameraType::REVERSED_Z)
}
ty
}
}
#[repr(u32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum UBOBindingPoints{
Lighting = 0,
Material = 1,
Camera = 2,
SceneCamera = 3,
}
impl UBOBindingPoints{
pub fn ubo_name(self) -> &'static str{
match self{
UBOBindingPoints::Lighting => "light_data",
UBOBindingPoints::Material => "material_data",
UBOBindingPoints::Camera => "camera_data",
UBOBindingPoints::SceneCamera => "scene_camera_data",
}
}
pub fn to_uniform_block_binding(self) -> glin::program::Uniform{
glin::program::uniform(self.ubo_name(), &glin::program::UniformValue::UniformBlockBinding(self as u32))
}
pub fn to_buffer_binding<T, B: glin::BufferRange<T>>(self, buffer: B) -> glin::Property{
glin::Property::BufferBaseBinding(gl::UNIFORM_BUFFER, self as u32, buffer)
}
}
pub(crate) fn info_gl_blend_func(blend: BlendFactor) -> GLenum{
let func = match blend {
BlendFactor::Zero => gl::ZERO,
BlendFactor::One => gl::ONE,
BlendFactor::SrcAlpha => gl::SRC_ALPHA,
BlendFactor::OneMinusSrcAlpha => gl::ONE_MINUS_SRC_ALPHA,
BlendFactor::DstAlpha => gl::DST_ALPHA,
BlendFactor::OneMinusDstAlpha => gl::ONE_MINUS_DST_ALPHA,
BlendFactor::SrcColor => gl::SRC_COLOR,
BlendFactor::OneMinusSrcColor => gl::ONE_MINUS_SRC_COLOR,
BlendFactor::DstColor => gl::DST_COLOR,
BlendFactor::OneMinusDstColor => gl::ONE_MINUS_DST_COLOR,
};
func
}
pub trait AlphayTypeToGlProperties {
fn into_gl_properties(self) -> Vec<gl::Property>;
}
impl AlphayTypeToGlProperties for AlphaType {
fn into_gl_properties(self) -> Vec<gl::Property> {
match self {
AlphaType::None => vec![],
AlphaType::AlphaToCoverage => vec![gl::Property::SampleAlphaToCoverage(true)],
AlphaType::Blending => vec![
gl::Property::Blend(true),
gl::Property::BlendFuncSeparate(
gl::SRC_ALPHA,
gl::ONE_MINUS_SRC_ALPHA,
gl::ONE,
gl::ONE_MINUS_SRC_ALPHA),
],
AlphaType::BlendingFactors(color, alpha) => {
let src_colorfunc = info_gl_blend_func(color.src);
let dst_colorfunc = info_gl_blend_func(color.dst);
let src_alphafunc = info_gl_blend_func(alpha.src);
let dst_alphafunc = info_gl_blend_func(alpha.dst);
vec![
gl::Property::Blend(true),
gl::Property::BlendFuncSeparate(
src_colorfunc,
dst_colorfunc,
src_alphafunc,
dst_alphafunc,
),
]
},
AlphaType::ScreenDoor => vec![],
AlphaType::Threshold => vec![],
}
}
}
pub trait MaterialParameterAsUniformValue {
fn as_uniform_value(&self) -> UniformValue;
}
#[cfg(not(any(feature="gles", feature="webgl")))]
impl<'a> MaterialParameterAsUniformValue for UniformRef<'a>{
fn as_uniform_value(&self) -> UniformValue {
match self.value() {
UniformValueRef::Float(v) => UniformValue::Float(*v),
UniformValueRef::I32(v) => UniformValue::Int(*v),
UniformValueRef::U32(v) => UniformValue::UInt(*v),
UniformValueRef::Bool(v) => UniformValue::Bool(*v),
UniformValueRef::Vec2(v) => UniformValue::Vec2(v.x, v.y),
UniformValueRef::Vec3(v) => UniformValue::Vec3(v.x, v.y, v.z),
UniformValueRef::Vec4(v) => UniformValue::Vec4(v.x, v.y, v.z, v.w),
UniformValueRef::IVec2(v) => UniformValue::IVec2(v.x, v.y),
UniformValueRef::IVec3(v) => UniformValue::IVec3(v.x, v.y, v.z),
UniformValueRef::IVec4(v) => UniformValue::IVec4(v.x, v.y, v.z, v.w),
UniformValueRef::UVec2(v) => UniformValue::UVec2(v.x, v.y),
UniformValueRef::UVec3(v) => UniformValue::UVec3(v.x, v.y, v.z),
UniformValueRef::UVec4(v) => UniformValue::UVec4(v.x, v.y, v.z, v.w),
UniformValueRef::Rgb(v) => UniformValue::Vec3(v.r, v.g, v.b),
UniformValueRef::Rgba(v) => UniformValue::Vec4(v.c.r, v.c.g, v.c.b, v.a),
UniformValueRef::RgbLinear(v) => UniformValue::Vec3(v.r, v.g, v.b),
UniformValueRef::RgbaLinear(v) => UniformValue::Vec4(v.c.r, v.c.g, v.c.b, v.a),
UniformValueRef::Texture(_) => unimplemented!(),
UniformValueRef::Cubemap(_) => unimplemented!(),
UniformValueRef::Rad(v) => UniformValue::Float(v.value()),
UniformValueRef::Deg(v) => UniformValue::Float(v.value()),
UniformValueRef::Mat3(v) => UniformValue::Mat3(*v.as_ref()),
UniformValueRef::Mat4(v) => UniformValue::Mat4(*v.as_ref()),
UniformValueRef::ArrayFloat(v) => UniformValue::ArrayFloat(v.clone()),
UniformValueRef::ArrayVec2(v) => UniformValue::ArrayVec2(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayVec3(v) => UniformValue::ArrayVec3(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayVec4(v) => UniformValue::ArrayVec4(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayInt(v) => UniformValue::ArrayInt(v.clone()),
UniformValueRef::ArrayIVec2(v) => UniformValue::ArrayIVec2(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayIVec3(v) => UniformValue::ArrayIVec3(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayIVec4(v) => UniformValue::ArrayIVec4(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayUInt(v) => UniformValue::ArrayUInt(v.clone()),
UniformValueRef::ArrayUVec2(v) => UniformValue::ArrayUVec2(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayUVec3(v) => UniformValue::ArrayUVec3(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayUVec4(v) => UniformValue::ArrayUVec4(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::OptionFloat(v) => UniformValue::Float(v.unwrap()),
UniformValueRef::OptionI32(v) => UniformValue::Int(v.unwrap()),
UniformValueRef::OptionU32(v) => UniformValue::UInt(v.unwrap()),
UniformValueRef::OptionBool(v) => UniformValue::Bool(v.unwrap()),
UniformValueRef::OptionVec2(v) => UniformValue::Vec2(v.unwrap().x, v.unwrap().y),
UniformValueRef::OptionVec3(v) => UniformValue::Vec3(v.unwrap().x, v.unwrap().y, v.unwrap().z),
UniformValueRef::OptionVec4(v) => UniformValue::Vec4(v.unwrap().x, v.unwrap().y, v.unwrap().z, v.unwrap().w),
UniformValueRef::OptionIVec2(v) => UniformValue::IVec2(v.unwrap().x, v.unwrap().y),
UniformValueRef::OptionIVec3(v) => UniformValue::IVec3(v.unwrap().x, v.unwrap().y, v.unwrap().z),
UniformValueRef::OptionIVec4(v) => UniformValue::IVec4(v.unwrap().x, v.unwrap().y, v.unwrap().z, v.unwrap().w),
UniformValueRef::OptionUVec2(v) => UniformValue::UVec2(v.unwrap().x, v.unwrap().y),
UniformValueRef::OptionUVec3(v) => UniformValue::UVec3(v.unwrap().x, v.unwrap().y, v.unwrap().z),
UniformValueRef::OptionUVec4(v) => UniformValue::UVec4(v.unwrap().x, v.unwrap().y, v.unwrap().z, v.unwrap().w),
UniformValueRef::OptionRgb(v) => UniformValue::Vec3(v.unwrap().r, v.unwrap().g, v.unwrap().b),
UniformValueRef::OptionRgba(v) => UniformValue::Vec4(v.unwrap().c.r, v.unwrap().c.g, v.unwrap().c.b, v.unwrap().a),
UniformValueRef::OptionRgbLinear(v) => UniformValue::Vec3(v.unwrap().r, v.unwrap().g, v.unwrap().b),
UniformValueRef::OptionRgbaLinear(v) => UniformValue::Vec4(v.unwrap().c.r, v.unwrap().c.g, v.unwrap().c.b, v.unwrap().a),
UniformValueRef::OptionTexture(_) => unimplemented!(),
UniformValueRef::OptionCubemap(_) => unimplemented!(),
UniformValueRef::OptionRad(v) => UniformValue::Float(v.unwrap().value()),
UniformValueRef::OptionDeg(v) => UniformValue::Float(v.unwrap().value()),
UniformValueRef::OptionMat3(v) => UniformValue::Mat3(*v.unwrap().as_ref()),
UniformValueRef::OptionMat4(v) => UniformValue::Mat4(*v.unwrap().as_ref()),
UniformValueRef::OptionArrayFloat(v) => UniformValue::ArrayFloat(v.clone().unwrap()),
UniformValueRef::OptionArrayVec2(v) => UniformValue::ArrayVec2(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayVec3(v) => UniformValue::ArrayVec3(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayVec4(v) => UniformValue::ArrayVec4(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayInt(v) => UniformValue::ArrayInt(v.clone().unwrap()),
UniformValueRef::OptionArrayIVec2(v) => UniformValue::ArrayIVec2(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayIVec3(v) => UniformValue::ArrayIVec3(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayIVec4(v) => UniformValue::ArrayIVec4(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayUInt(v) => UniformValue::ArrayUInt(v.clone().unwrap()),
UniformValueRef::OptionArrayUVec2(v) => UniformValue::ArrayUVec2(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayUVec3(v) => UniformValue::ArrayUVec3(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayUVec4(v) => UniformValue::ArrayUVec4(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
}
}
}
#[cfg(any(feature="gles", feature="webgl"))]
impl<'a> MaterialParameterAsUniformValue for ParameterRef<'a>{
fn as_uniform_value(&self) -> UniformValue {
match self.parameter_value_ref(){
UniformValueRef::Float(v) => UniformValue::Float(*v),
UniformValueRef::I32(v) => UniformValue::Int(*v),
UniformValueRef::U32(v) => UniformValue::Int(*v as i32),
UniformValueRef::Bool(v) => UniformValue::Bool(*v),
UniformValueRef::Vec2(v) => UniformValue::Vec2(v.x, v.y),
UniformValueRef::Vec3(v) => UniformValue::Vec3(v.x, v.y, v.z),
UniformValueRef::Vec4(v) => UniformValue::Vec4(v.x, v.y, v.z, v.w),
UniformValueRef::IVec2(v) => UniformValue::IVec2(v.x, v.y),
UniformValueRef::IVec3(v) => UniformValue::IVec3(v.x, v.y, v.z),
UniformValueRef::IVec4(v) => UniformValue::IVec4(v.x, v.y, v.z, v.w),
UniformValueRef::Rgb(v) => UniformValue::Vec3(v.r, v.g, v.b),
UniformValueRef::Rgba(v) => UniformValue::Vec4(v.c.r, v.c.g, v.c.b, v.a),
UniformValueRef::RgbLinear(v) => UniformValue::Vec3(v.r, v.g, v.b),
UniformValueRef::RgbaLinear(v) => UniformValue::Vec4(v.c.r, v.c.g, v.c.b, v.a),
UniformValueRef::Texture(v) => unimplemented!(),
UniformValueRef::Cubemap(v) => unimplemented!(),
UniformValueRef::Rad(v) => UniformValue::Float(v.value()),
UniformValueRef::Deg(v) => UniformValue::Float(v.value()),
UniformValueRef::Mat3(v) => UniformValue::Mat3(*v.as_ref()),
UniformValueRef::Mat4(v) => UniformValue::Mat4(*v.as_ref()),
UniformValueRef::ArrayFloat(v) => UniformValue::ArrayFloat(v.clone()),
UniformValueRef::ArrayVec2(v) => UniformValue::ArrayVec2(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayVec3(v) => UniformValue::ArrayVec3(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayVec4(v) => UniformValue::ArrayVec4(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayInt(v) => UniformValue::ArrayInt(v.clone()),
UniformValueRef::ArrayIVec2(v) => UniformValue::ArrayIVec2(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayIVec3(v) => UniformValue::ArrayIVec3(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::ArrayIVec4(v) => UniformValue::ArrayIVec4(unsafe{ std::mem::transmute(v.clone()) }),
UniformValueRef::OptionFloat(v) => UniformValue::Float(v.unwrap()),
UniformValueRef::OptionI32(v) => UniformValue::Int(v.unwrap()),
UniformValueRef::OptionU32(v) => UniformValue::Int(v.unwrap() as i32),
UniformValueRef::OptionBool(v) => UniformValue::Bool(v.unwrap()),
UniformValueRef::OptionVec2(v) => UniformValue::Vec2(v.unwrap().x, v.unwrap().y),
UniformValueRef::OptionVec3(v) => UniformValue::Vec3(v.unwrap().x, v.unwrap().y, v.unwrap().z),
UniformValueRef::OptionVec4(v) => UniformValue::Vec4(v.unwrap().x, v.unwrap().y, v.unwrap().z, v.unwrap().w),
UniformValueRef::OptionIVec2(v) => UniformValue::IVec2(v.unwrap().x, v.unwrap().y),
UniformValueRef::OptionIVec3(v) => UniformValue::IVec3(v.unwrap().x, v.unwrap().y, v.unwrap().z),
UniformValueRef::OptionIVec4(v) => UniformValue::IVec4(v.unwrap().x, v.unwrap().y, v.unwrap().z, v.unwrap().w),
UniformValueRef::OptionRgb(v) => UniformValue::Vec3(v.unwrap().r, v.unwrap().g, v.unwrap().b),
UniformValueRef::OptionRgba(v) => UniformValue::Vec4(v.unwrap().c.r, v.unwrap().c.g, v.unwrap().c.b, v.unwrap().a),
UniformValueRef::OptionRgbLinear(v) => UniformValue::Vec3(v.unwrap().r, v.unwrap().g, v.unwrap().b),
UniformValueRef::OptionRgbaLinear(v) => UniformValue::Vec4(v.unwrap().c.r, v.unwrap().c.g, v.unwrap().c.b, v.unwrap().a),
UniformValueRef::OptionTexture(v) => unimplemented!(),
UniformValueRef::OptionCubemap(v) => unimplemented!(),
UniformValueRef::OptionRad(v) => UniformValue::Float(v.unwrap().value()),
UniformValueRef::OptionDeg(v) => UniformValue::Float(v.unwrap().value()),
UniformValueRef::OptionMat3(v) => UniformValue::Mat3(*v.unwrap().as_ref()),
UniformValueRef::OptionMat4(v) => UniformValue::Mat4(*v.unwrap().as_ref()),
UniformValueRef::OptionArrayFloat(v) => UniformValue::ArrayFloat(v.clone().unwrap()),
UniformValueRef::OptionArrayVec2(v) => UniformValue::ArrayVec2(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayVec3(v) => UniformValue::ArrayVec3(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayVec4(v) => UniformValue::ArrayVec4(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayInt(v) => UniformValue::ArrayInt(v.clone().unwrap()),
UniformValueRef::OptionArrayIVec2(v) => UniformValue::ArrayIVec2(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayIVec3(v) => UniformValue::ArrayIVec3(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
UniformValueRef::OptionArrayIVec4(v) => UniformValue::ArrayIVec4(unsafe{ std::mem::transmute(v.clone().unwrap()) }),
}
}
}