mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
isolated all unsafe opengl calls into framework mod
This commit is contained in:
+2
-1
@@ -2,4 +2,5 @@
|
||||
**/*.rs.bk
|
||||
/cloc
|
||||
*.lock
|
||||
.*
|
||||
.*
|
||||
/*.log
|
||||
+12
-17
@@ -19,7 +19,6 @@ use crate::{
|
||||
renderer::{
|
||||
Renderer,
|
||||
error::RendererError,
|
||||
gl,
|
||||
},
|
||||
window::{
|
||||
WindowBuilder,
|
||||
@@ -33,12 +32,12 @@ use crate::{
|
||||
NotCurrent,
|
||||
Api,
|
||||
event_loop::EventLoop,
|
||||
gui::Control
|
||||
gui::Control,
|
||||
};
|
||||
use std::{
|
||||
sync::{Arc, Mutex},
|
||||
time,
|
||||
time::Duration
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
pub struct Engine<M: 'static, C: 'static + Control<M, C>> {
|
||||
@@ -48,7 +47,7 @@ pub struct Engine<M: 'static, C: 'static + Control<M, C>> {
|
||||
pub sound_context: Arc<Mutex<Context>>,
|
||||
pub resource_manager: Arc<Mutex<ResourceManager>>,
|
||||
pub scenes: SceneContainer,
|
||||
pub ui_time: Duration
|
||||
pub ui_time: Duration,
|
||||
}
|
||||
|
||||
impl<M, C: 'static + Control<M, C>> Engine<M, C> {
|
||||
@@ -70,32 +69,28 @@ impl<M, C: 'static + Control<M, C>> Engine<M, C> {
|
||||
/// let mut engine = Engine::new(window_builder, &evt).unwrap();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn new(window_builder: WindowBuilder, events_loop: &EventLoop<()>) -> Result<Engine<M, C> , EngineError> {
|
||||
pub fn new(window_builder: WindowBuilder, events_loop: &EventLoop<()>) -> Result<Engine<M, C>, EngineError> {
|
||||
let context_wrapper: WindowedContext<NotCurrent> = glutin::ContextBuilder::new()
|
||||
.with_vsync(true)
|
||||
.with_gl_profile(GlProfile::Core)
|
||||
.with_gl(GlRequest::Specific(Api::OpenGl, (3, 3)))
|
||||
.build_windowed(window_builder, events_loop)?;
|
||||
|
||||
let context = unsafe {
|
||||
let context = match context_wrapper.make_current() {
|
||||
Ok(context) => context,
|
||||
Err((_, e)) => return Err(EngineError::from(e)),
|
||||
};
|
||||
gl::load_with(|symbol| context.get_proc_address(symbol) as *const _);
|
||||
context
|
||||
let mut context = match unsafe { context_wrapper.make_current() } {
|
||||
Ok(context) => context,
|
||||
Err((_, e)) => return Err(EngineError::from(e)),
|
||||
};
|
||||
|
||||
let client_size = context.window().inner_size();
|
||||
|
||||
Ok(Engine {
|
||||
context,
|
||||
renderer: Renderer::new(&mut context, client_size.into())?,
|
||||
resource_manager: Arc::new(Mutex::new(ResourceManager::new())),
|
||||
sound_context: Context::new()?,
|
||||
scenes: SceneContainer::new(),
|
||||
renderer: Renderer::new(client_size.into())?,
|
||||
user_interface: UserInterface::new(),
|
||||
ui_time: Default::default()
|
||||
ui_time: Default::default(),
|
||||
context,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -129,7 +124,7 @@ impl<M, C: 'static + Control<M, C>> Engine<M, C> {
|
||||
self.ui_time = time::Instant::now() - time;
|
||||
}
|
||||
|
||||
pub fn get_ui_mut(&mut self) -> &mut UserInterface<M, C> {
|
||||
pub fn get_ui_mut(&mut self) -> &mut UserInterface<M, C> {
|
||||
&mut self.user_interface
|
||||
}
|
||||
|
||||
@@ -140,7 +135,7 @@ impl<M, C: 'static + Control<M, C>> Engine<M, C> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: 'static, C: 'static + Control<M, C>> Visit for Engine<M, C> {
|
||||
impl<M: 'static, C: 'static + Control<M, C>> Visit for Engine<M, C> {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
visitor.enter_region(name)?;
|
||||
|
||||
|
||||
@@ -11,26 +11,28 @@ use crate::{
|
||||
scene::camera::Camera,
|
||||
renderer::{
|
||||
RenderPassStatistics,
|
||||
gpu_program::{
|
||||
UniformLocation,
|
||||
GpuProgram,
|
||||
UniformValue
|
||||
},
|
||||
geometry_buffer::{
|
||||
GeometryBuffer,
|
||||
GeometryBufferKind,
|
||||
AttributeDefinition,
|
||||
AttributeKind,
|
||||
ElementKind
|
||||
},
|
||||
error::RendererError,
|
||||
framebuffer::{
|
||||
FrameBufferTrait,
|
||||
DrawParameters,
|
||||
CullFace,
|
||||
FrameBuffer
|
||||
},
|
||||
state::State
|
||||
framework::{
|
||||
framebuffer::{
|
||||
FrameBufferTrait,
|
||||
DrawParameters,
|
||||
CullFace,
|
||||
FrameBuffer
|
||||
},
|
||||
geometry_buffer::{
|
||||
GeometryBuffer,
|
||||
GeometryBufferKind,
|
||||
AttributeDefinition,
|
||||
AttributeKind,
|
||||
ElementKind
|
||||
},
|
||||
gpu_program::{
|
||||
UniformLocation,
|
||||
GpuProgram,
|
||||
UniformValue
|
||||
},
|
||||
state::State
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -59,7 +61,7 @@ impl DebugShader {
|
||||
let vertex_source = include_str!("shaders/debug_vs.glsl");
|
||||
let mut program = GpuProgram::from_source("DebugShader", &vertex_source, &fragment_source)?;
|
||||
Ok(Self {
|
||||
wvp_matrix: program.get_uniform_location("worldViewProjection")?,
|
||||
wvp_matrix: program.uniform_location("worldViewProjection")?,
|
||||
program,
|
||||
})
|
||||
}
|
||||
@@ -185,7 +187,7 @@ impl DebugRenderer {
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Back,
|
||||
culling: false,
|
||||
color_write: (true, true, true, true),
|
||||
color_write: Default::default(),
|
||||
depth_write: false,
|
||||
stencil_test: false,
|
||||
depth_test: true,
|
||||
|
||||
@@ -4,31 +4,38 @@ use std::{
|
||||
};
|
||||
use crate::{
|
||||
renderer::{
|
||||
framebuffer::{
|
||||
DrawParameters,
|
||||
CullFace,
|
||||
FrameBufferTrait
|
||||
},
|
||||
flat_shader::FlatShader,
|
||||
surface::SurfaceSharedData,
|
||||
gpu_program::{
|
||||
UniformLocation,
|
||||
GpuProgram,
|
||||
UniformValue,
|
||||
framework::{
|
||||
gl,
|
||||
gpu_texture::GpuTexture,
|
||||
gpu_program::{
|
||||
UniformLocation,
|
||||
GpuProgram,
|
||||
UniformValue,
|
||||
},
|
||||
framebuffer::{
|
||||
DrawParameters,
|
||||
CullFace,
|
||||
FrameBufferTrait,
|
||||
},
|
||||
state::{
|
||||
State,
|
||||
ColorMask,
|
||||
StencilFunc,
|
||||
StencilOp
|
||||
}
|
||||
},
|
||||
gl,
|
||||
gbuffer::GBuffer,
|
||||
error::RendererError,
|
||||
shadow_map_renderer::{
|
||||
SpotShadowMapRenderer,
|
||||
PointShadowMapRenderer,
|
||||
},
|
||||
gpu_texture::GpuTexture,
|
||||
QualitySettings,
|
||||
RenderPassStatistics,
|
||||
GeometryCache,
|
||||
TextureCache,
|
||||
state::State
|
||||
},
|
||||
scene::{
|
||||
camera::Camera,
|
||||
@@ -61,9 +68,9 @@ impl AmbientLightShader {
|
||||
let vertex_source = include_str!("shaders/ambient_light_vs.glsl");
|
||||
let mut program = GpuProgram::from_source("AmbientLightShader", vertex_source, fragment_source)?;
|
||||
Ok(Self {
|
||||
wvp_matrix: program.get_uniform_location("worldViewProjection")?,
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture")?,
|
||||
ambient_color: program.get_uniform_location("ambientColor")?,
|
||||
wvp_matrix: program.uniform_location("worldViewProjection")?,
|
||||
diffuse_texture: program.uniform_location("diffuseTexture")?,
|
||||
ambient_color: program.uniform_location("ambientColor")?,
|
||||
program,
|
||||
})
|
||||
}
|
||||
@@ -97,24 +104,24 @@ impl DeferredLightingShader {
|
||||
let vertex_source = include_str!("shaders/deferred_light_vs.glsl");
|
||||
let mut program = GpuProgram::from_source("DeferredLightShader", vertex_source, fragment_source)?;
|
||||
Ok(Self {
|
||||
wvp_matrix: program.get_uniform_location("worldViewProjection")?,
|
||||
depth_sampler: program.get_uniform_location("depthTexture")?,
|
||||
color_sampler: program.get_uniform_location("colorTexture")?,
|
||||
normal_sampler: program.get_uniform_location("normalTexture")?,
|
||||
spot_shadow_texture: program.get_uniform_location("spotShadowTexture")?,
|
||||
point_shadow_texture: program.get_uniform_location("pointShadowTexture")?,
|
||||
light_view_proj_matrix: program.get_uniform_location("lightViewProjMatrix")?,
|
||||
light_type: program.get_uniform_location("lightType")?,
|
||||
soft_shadows: program.get_uniform_location("softShadows")?,
|
||||
shadow_map_inv_size: program.get_uniform_location("shadowMapInvSize")?,
|
||||
light_position: program.get_uniform_location("lightPos")?,
|
||||
light_radius: program.get_uniform_location("lightRadius")?,
|
||||
light_color: program.get_uniform_location("lightColor")?,
|
||||
light_direction: program.get_uniform_location("lightDirection")?,
|
||||
half_hotspot_cone_angle_cos: program.get_uniform_location("halfHotspotConeAngleCos")?,
|
||||
half_cone_angle_cos: program.get_uniform_location("halfConeAngleCos")?,
|
||||
inv_view_proj_matrix: program.get_uniform_location("invViewProj")?,
|
||||
camera_position: program.get_uniform_location("cameraPosition")?,
|
||||
wvp_matrix: program.uniform_location("worldViewProjection")?,
|
||||
depth_sampler: program.uniform_location("depthTexture")?,
|
||||
color_sampler: program.uniform_location("colorTexture")?,
|
||||
normal_sampler: program.uniform_location("normalTexture")?,
|
||||
spot_shadow_texture: program.uniform_location("spotShadowTexture")?,
|
||||
point_shadow_texture: program.uniform_location("pointShadowTexture")?,
|
||||
light_view_proj_matrix: program.uniform_location("lightViewProjMatrix")?,
|
||||
light_type: program.uniform_location("lightType")?,
|
||||
soft_shadows: program.uniform_location("softShadows")?,
|
||||
shadow_map_inv_size: program.uniform_location("shadowMapInvSize")?,
|
||||
light_position: program.uniform_location("lightPos")?,
|
||||
light_radius: program.uniform_location("lightRadius")?,
|
||||
light_color: program.uniform_location("lightColor")?,
|
||||
light_direction: program.uniform_location("lightDirection")?,
|
||||
half_hotspot_cone_angle_cos: program.uniform_location("halfHotspotConeAngleCos")?,
|
||||
half_cone_angle_cos: program.uniform_location("halfConeAngleCos")?,
|
||||
inv_view_proj_matrix: program.uniform_location("invViewProj")?,
|
||||
camera_position: program.uniform_location("cameraPosition")?,
|
||||
|
||||
program,
|
||||
})
|
||||
@@ -188,7 +195,7 @@ impl DeferredLightRenderer {
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Back,
|
||||
culling: false,
|
||||
color_write: (true, true, true, true),
|
||||
color_write: Default::default(),
|
||||
depth_write: false,
|
||||
stencil_test: false,
|
||||
depth_test: false,
|
||||
@@ -283,11 +290,8 @@ impl DeferredLightRenderer {
|
||||
|
||||
// Mark lighted areas in stencil buffer to do light calculations only on them.
|
||||
context.state.set_stencil_mask(0xFFFF_FFFF);
|
||||
|
||||
unsafe {
|
||||
gl::StencilFunc(gl::ALWAYS, 0, 0xFF);
|
||||
gl::StencilOp(gl::KEEP, gl::INCR, gl::KEEP);
|
||||
}
|
||||
context.state.set_stencil_func(StencilFunc { func: gl::ALWAYS, ..Default::default() });
|
||||
context.state.set_stencil_op(StencilOp { zfail: gl::INCR, ..Default::default() });
|
||||
|
||||
statistics.add_draw_call(context.gbuffer.opt_framebuffer.draw(
|
||||
context.state,
|
||||
@@ -297,7 +301,7 @@ impl DeferredLightRenderer {
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Front,
|
||||
culling: true,
|
||||
color_write: (false, false, false, false),
|
||||
color_write: ColorMask::all(false),
|
||||
depth_write: false,
|
||||
stencil_test: true,
|
||||
depth_test: true,
|
||||
@@ -310,10 +314,8 @@ impl DeferredLightRenderer {
|
||||
],
|
||||
));
|
||||
|
||||
unsafe {
|
||||
gl::StencilFunc(gl::ALWAYS, 0, 0xFF);
|
||||
gl::StencilOp(gl::KEEP, gl::DECR, gl::KEEP);
|
||||
}
|
||||
context.state.set_stencil_func(StencilFunc { func: gl::ALWAYS, ..Default::default() });
|
||||
context.state.set_stencil_op(StencilOp { zfail: gl::DECR, ..Default::default() });
|
||||
|
||||
statistics.add_draw_call(context.gbuffer.opt_framebuffer.draw(
|
||||
context.state,
|
||||
@@ -323,7 +325,7 @@ impl DeferredLightRenderer {
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Back,
|
||||
culling: true,
|
||||
color_write: (false, false, false, false),
|
||||
color_write: ColorMask::all(false),
|
||||
depth_write: false,
|
||||
stencil_test: true,
|
||||
depth_test: true,
|
||||
@@ -336,10 +338,8 @@ impl DeferredLightRenderer {
|
||||
],
|
||||
));
|
||||
|
||||
unsafe {
|
||||
gl::StencilFunc(gl::NOTEQUAL, 0, 0xFF);
|
||||
gl::StencilOp(gl::KEEP, gl::KEEP, gl::ZERO);
|
||||
}
|
||||
context.state.set_stencil_func(StencilFunc { func: gl::NOTEQUAL, ..Default::default() });
|
||||
context.state.set_stencil_op(StencilOp { zpass: gl::ZERO, ..Default::default() });
|
||||
|
||||
let (hotspot_cone_angle, cone_angle) = match light.get_kind() {
|
||||
LightKind::Spot(spot_light) => (spot_light.hotspot_cone_angle(), spot_light.full_cone_angle()),
|
||||
@@ -355,7 +355,7 @@ impl DeferredLightRenderer {
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Back,
|
||||
culling: false,
|
||||
color_write: (true, true, true, true),
|
||||
color_write: Default::default(),
|
||||
depth_write: false,
|
||||
stencil_test: true,
|
||||
depth_test: false,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::renderer::{
|
||||
gpu_program::{
|
||||
framework::gpu_program::{
|
||||
GpuProgram,
|
||||
UniformLocation,
|
||||
},
|
||||
@@ -19,8 +19,8 @@ impl FlatShader {
|
||||
|
||||
let mut program = GpuProgram::from_source("FlatShader", vertex_source, fragment_source)?;
|
||||
Ok(Self {
|
||||
wvp_matrix: program.get_uniform_location("worldViewProjection")?,
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture")?,
|
||||
wvp_matrix: program.uniform_location("worldViewProjection")?,
|
||||
diffuse_texture: program.uniform_location("diffuseTexture")?,
|
||||
program,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,20 +8,23 @@ use crate::{
|
||||
color::Color,
|
||||
},
|
||||
renderer::{
|
||||
gl::{
|
||||
types::GLuint,
|
||||
self,
|
||||
},
|
||||
error::RendererError,
|
||||
gpu_texture::{
|
||||
GpuTexture,
|
||||
GpuTextureKind,
|
||||
CubeMapFace,
|
||||
},
|
||||
geometry_buffer::GeometryBuffer,
|
||||
gpu_program::{UniformLocation, GpuProgram, UniformValue},
|
||||
state::State,
|
||||
},
|
||||
framework::{
|
||||
geometry_buffer::GeometryBuffer,
|
||||
gpu_texture::{
|
||||
GpuTexture,
|
||||
GpuTextureKind,
|
||||
CubeMapFace,
|
||||
},
|
||||
gl::{
|
||||
types::GLuint,
|
||||
self,
|
||||
},
|
||||
gpu_program::{UniformLocation, GpuProgram, UniformValue},
|
||||
state::State,
|
||||
state::ColorMask
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, PartialOrd, PartialEq, Hash, Debug)]
|
||||
@@ -60,7 +63,7 @@ impl CullFace {
|
||||
pub struct DrawParameters {
|
||||
pub cull_face: CullFace,
|
||||
pub culling: bool,
|
||||
pub color_write: (bool, bool, bool, bool),
|
||||
pub color_write: ColorMask,
|
||||
pub depth_write: bool,
|
||||
pub stencil_test: bool,
|
||||
pub depth_test: bool,
|
||||
@@ -72,7 +75,7 @@ impl Default for DrawParameters {
|
||||
Self {
|
||||
cull_face: CullFace::Back,
|
||||
culling: true,
|
||||
color_write: (true, true, true, true),
|
||||
color_write: Default::default(),
|
||||
depth_write: true,
|
||||
stencil_test: false,
|
||||
depth_test: true,
|
||||
@@ -178,9 +181,9 @@ fn pre_draw(fbo: GLuint,
|
||||
state.set_viewport(viewport);
|
||||
state.apply_draw_parameters(¶ms);
|
||||
|
||||
program.bind();
|
||||
program.bind(state);
|
||||
for (location, value) in uniforms {
|
||||
program.set_uniform(*location, value)
|
||||
program.set_uniform(state, *location, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +197,7 @@ pub trait FrameBufferTrait {
|
||||
state.set_framebuffer(self.id());
|
||||
|
||||
if let Some(color) = color {
|
||||
state.set_color_write((true, true, true, true));
|
||||
state.set_color_write(ColorMask::default());
|
||||
state.set_clear_color(color);
|
||||
mask |= gl::COLOR_BUFFER_BIT;
|
||||
}
|
||||
@@ -234,7 +237,7 @@ pub trait FrameBufferTrait {
|
||||
params: DrawParameters,
|
||||
uniforms: &[(UniformLocation, UniformValue<'_>)],
|
||||
offset: usize,
|
||||
count: usize
|
||||
count: usize,
|
||||
) -> Result<usize, RendererError> {
|
||||
pre_draw(self.id(), state, viewport, program, params, uniforms);
|
||||
geometry.bind().draw_part(offset, count)
|
||||
@@ -7,7 +7,7 @@ use std::{
|
||||
use crate::{
|
||||
renderer::{
|
||||
error::RendererError,
|
||||
gl::{
|
||||
framework::gl::{
|
||||
self,
|
||||
types::{GLuint, GLint}
|
||||
},
|
||||
@@ -5,7 +5,6 @@ use std::{
|
||||
cell::RefCell
|
||||
};
|
||||
use crate::{
|
||||
renderer::gpu_texture::GpuTexture,
|
||||
core::{
|
||||
math::{
|
||||
vec4::Vec4,
|
||||
@@ -17,13 +16,16 @@ use crate::{
|
||||
},
|
||||
renderer::{
|
||||
error::RendererError,
|
||||
gl::{
|
||||
self,
|
||||
types::{
|
||||
GLuint,
|
||||
GLint,
|
||||
GLfloat
|
||||
}
|
||||
framework::{
|
||||
gpu_texture::GpuTexture,
|
||||
gl::{
|
||||
self,
|
||||
types::{
|
||||
GLuint,
|
||||
GLint,
|
||||
}
|
||||
},
|
||||
state::State
|
||||
}
|
||||
},
|
||||
utils::log::Log,
|
||||
@@ -43,6 +45,7 @@ pub struct UniformLocation {
|
||||
thread_mark: PhantomData<*const u8>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum UniformValue<'a> {
|
||||
Sampler {
|
||||
index: usize,
|
||||
@@ -56,89 +59,16 @@ pub enum UniformValue<'a> {
|
||||
Vec3(Vec3),
|
||||
Vec4(Vec4),
|
||||
Color(Color),
|
||||
Mat4(Mat4),
|
||||
|
||||
IntegerArray(&'a [i32]),
|
||||
FloatArray(&'a [f32]),
|
||||
Vec2Array(&'a [Vec2]),
|
||||
Vec3Array(&'a [Vec3]),
|
||||
Vec4Array(&'a [Vec4]),
|
||||
Mat4(Mat4),
|
||||
Mat4Array(&'a [Mat4])
|
||||
}
|
||||
|
||||
pub struct GpuProgramBinding<'a> {
|
||||
_program: &'a mut GpuProgram
|
||||
}
|
||||
|
||||
impl<'a> GpuProgramBinding<'a> {
|
||||
pub fn set_mat4(&mut self, location: UniformLocation, mat: &Mat4) -> &mut Self {
|
||||
unsafe {
|
||||
gl::UniformMatrix4fv(location.id, 1, gl::FALSE, &mat.f as *const GLfloat);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_mat4_array(&mut self, location: UniformLocation, mat: &[Mat4]) -> &mut Self {
|
||||
unsafe {
|
||||
gl::UniformMatrix4fv(location.id, mat.len() as i32, gl::FALSE, mat[0].f.as_ptr() as *const GLfloat);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_int(&mut self, location: UniformLocation, value: i32) -> &mut Self {
|
||||
unsafe {
|
||||
gl::Uniform1i(location.id, value);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_vec4_array(&mut self, location: UniformLocation, v: &[Vec4]) -> &mut Self {
|
||||
unsafe {
|
||||
gl::Uniform4fv(location.id, v.len() as i32, v.as_ptr() as *const GLfloat);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_vec4(&mut self, location: UniformLocation, value: &Vec4) -> &mut Self {
|
||||
unsafe {
|
||||
gl::Uniform4f(location.id, value.x, value.y, value.z, value.w);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_bool(&mut self, location: UniformLocation, value: bool) -> &mut Self {
|
||||
self.set_int(location, i32::from(if value { gl::TRUE } else { gl::FALSE }))
|
||||
}
|
||||
|
||||
pub fn set_float(&mut self, location: UniformLocation, value: f32) -> &mut Self {
|
||||
unsafe {
|
||||
gl::Uniform1f(location.id, value)
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_float_array(&mut self, location: UniformLocation, v: &[f32]) -> &mut Self {
|
||||
unsafe {
|
||||
gl::Uniform1fv(location.id, v.len() as i32, v.as_ptr() as *const GLfloat);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_vec3(&mut self, location: UniformLocation, value: &Vec3) -> &mut Self {
|
||||
unsafe {
|
||||
gl::Uniform3f(location.id, value.x, value.y, value.z)
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_vec2(&mut self, location: UniformLocation, value: Vec2) -> &mut Self {
|
||||
unsafe {
|
||||
gl::Uniform2f(location.id, value.x, value.y)
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuProgram {
|
||||
fn create_shader(name: String, actual_type: GLuint, source: &str) -> Result<GLuint, RendererError> {
|
||||
unsafe {
|
||||
@@ -200,7 +130,7 @@ impl GpuProgram {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_uniform_location(&mut self, name: &str) -> Result<UniformLocation, RendererError> {
|
||||
pub fn uniform_location(&mut self, name: &str) -> Result<UniformLocation, RendererError> {
|
||||
// Form c string in special buffer to reduce memory allocations
|
||||
let buf = &mut self.name_buf;
|
||||
buf.clear();
|
||||
@@ -216,30 +146,19 @@ impl GpuProgram {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_bound(&self) -> bool {
|
||||
unsafe {
|
||||
let mut program = 0;
|
||||
gl::GetIntegerv(gl::CURRENT_PROGRAM, &mut program);
|
||||
self.id == program as u32
|
||||
}
|
||||
pub fn bind(&mut self, state: &mut State) {
|
||||
state.set_program(self.id);
|
||||
}
|
||||
|
||||
pub fn bind(&mut self) -> GpuProgramBinding<'_> {
|
||||
unsafe {
|
||||
gl::UseProgram(self.id);
|
||||
}
|
||||
GpuProgramBinding {
|
||||
_program: self
|
||||
}
|
||||
}
|
||||
pub fn set_uniform(&mut self, state: &mut State, location: UniformLocation, value: &UniformValue<'_>) {
|
||||
state.set_program(self.id);
|
||||
|
||||
pub fn set_uniform(&mut self, location: UniformLocation, value: &UniformValue<'_>) {
|
||||
let location = location.id;
|
||||
unsafe {
|
||||
match value {
|
||||
UniformValue::Sampler { index, texture } => {
|
||||
gl::Uniform1i(location, *index as i32);
|
||||
texture.borrow().bind(*index);
|
||||
texture.borrow().bind(state,*index);
|
||||
}
|
||||
UniformValue::Bool(value) => {
|
||||
gl::Uniform1i(location, if *value { gl::TRUE } else { gl::FALSE } as i32);
|
||||
@@ -8,8 +8,11 @@ use std::{
|
||||
use crate::{
|
||||
resource::texture::TextureKind,
|
||||
renderer::{
|
||||
gl::types::GLuint,
|
||||
gl,
|
||||
framework::{
|
||||
gl::types::GLuint,
|
||||
gl,
|
||||
state::State
|
||||
},
|
||||
error::RendererError,
|
||||
},
|
||||
utils::log::Log,
|
||||
@@ -243,7 +246,8 @@ impl GpuTexture {
|
||||
///
|
||||
/// Produced texture can be used as render target for framebuffer, in this case `data`
|
||||
/// parameter can be None.
|
||||
pub fn new(kind: GpuTextureKind,
|
||||
pub fn new(state: &mut State,
|
||||
kind: GpuTextureKind,
|
||||
pixel_kind: PixelKind,
|
||||
data: Option<&[u8]>) -> Result<Self, RendererError> {
|
||||
let bytes_per_pixel = pixel_kind.size_bytes();
|
||||
@@ -268,7 +272,8 @@ impl GpuTexture {
|
||||
unsafe {
|
||||
let mut texture = 0;
|
||||
gl::GenTextures(1, &mut texture);
|
||||
gl::BindTexture(target, texture);
|
||||
|
||||
state.set_texture(0, target, texture);
|
||||
|
||||
let (type_, format, internal_format) = match pixel_kind {
|
||||
PixelKind::F32 => (gl::FLOAT, gl::RED, gl::R32F),
|
||||
@@ -324,7 +329,7 @@ impl GpuTexture {
|
||||
gl::TexParameteri(target, gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32);
|
||||
gl::TexParameteri(target, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
|
||||
|
||||
gl::BindTexture(target, 0);
|
||||
state.set_texture(0, target, 0);
|
||||
|
||||
Log::writeln(format!("GL texture {} was created!", texture));
|
||||
|
||||
@@ -336,19 +341,13 @@ impl GpuTexture {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_mut(&mut self, sampler_index: usize) -> TextureBinding<'_> {
|
||||
unsafe {
|
||||
gl::ActiveTexture(gl::TEXTURE0 + sampler_index as u32);
|
||||
gl::BindTexture(self.kind.to_texture_target(), self.texture);
|
||||
}
|
||||
pub fn bind_mut(&mut self, state: &mut State, sampler_index: usize) -> TextureBinding<'_> {
|
||||
state.set_texture(sampler_index, self.kind.to_texture_target(), self.texture);
|
||||
TextureBinding { texture: self }
|
||||
}
|
||||
|
||||
pub fn bind(&self, sampler_index: usize) {
|
||||
unsafe {
|
||||
gl::ActiveTexture(gl::TEXTURE0 + sampler_index as u32);
|
||||
gl::BindTexture(self.kind.to_texture_target(), self.texture);
|
||||
}
|
||||
pub fn bind(&self, state: &mut State, sampler_index: usize) {
|
||||
state.set_texture(sampler_index, self.kind.to_texture_target(), self.texture);
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> GpuTextureKind {
|
||||
@@ -0,0 +1,132 @@
|
||||
use crate::utils::log::Log;
|
||||
use crate::renderer::framework::gl::types::{GLchar, GLenum, GLuint, GLsizei};
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[allow(clippy::all)]
|
||||
pub(in crate) mod gl;
|
||||
|
||||
macro_rules! check_gl_error {
|
||||
() => (crate::renderer::framework::check_gl_error_internal(line!(), file!()))
|
||||
}
|
||||
|
||||
pub mod gpu_program;
|
||||
pub mod geometry_buffer;
|
||||
pub mod gpu_texture;
|
||||
pub mod framebuffer;
|
||||
pub mod state;
|
||||
|
||||
pub fn check_gl_error_internal(line: u32, file: &str) {
|
||||
unsafe {
|
||||
let error_code = gl::GetError();
|
||||
if error_code != gl::NO_ERROR {
|
||||
let code = match error_code {
|
||||
gl::INVALID_ENUM => "GL_INVALID_ENUM",
|
||||
gl::INVALID_VALUE => "GL_INVALID_VALUE",
|
||||
gl::INVALID_OPERATION => "GL_INVALID_OPERATION",
|
||||
gl::STACK_OVERFLOW => "GL_STACK_OVERFLOW",
|
||||
gl::STACK_UNDERFLOW => "GL_STACK_UNDERFLOW",
|
||||
gl::OUT_OF_MEMORY => "GL_OUT_OF_MEMORY",
|
||||
_ => "Unknown",
|
||||
};
|
||||
|
||||
Log::writeln(format!("{} error has occurred! At line {} in file {}, stability is not guaranteed!", code, line, file));
|
||||
|
||||
if gl::GetDebugMessageLog::is_loaded() {
|
||||
let mut max_message_length = 0;
|
||||
gl::GetIntegerv(gl::MAX_DEBUG_MESSAGE_LENGTH, &mut max_message_length);
|
||||
|
||||
let mut max_logged_messages = 0;
|
||||
gl::GetIntegerv(gl::MAX_DEBUG_LOGGED_MESSAGES, &mut max_logged_messages);
|
||||
|
||||
let buffer_size = max_message_length * max_logged_messages;
|
||||
|
||||
let mut message_buffer: Vec<GLchar> = Vec::with_capacity(buffer_size as usize);
|
||||
message_buffer.set_len(buffer_size as usize);
|
||||
|
||||
let mut sources: Vec<GLenum> = Vec::with_capacity(max_logged_messages as usize);
|
||||
sources.set_len(max_logged_messages as usize);
|
||||
|
||||
let mut types: Vec<GLenum> = Vec::with_capacity(max_logged_messages as usize);
|
||||
types.set_len(max_logged_messages as usize);
|
||||
|
||||
let mut ids: Vec<GLuint> = Vec::with_capacity(max_logged_messages as usize);
|
||||
ids.set_len(max_logged_messages as usize);
|
||||
|
||||
let mut severities: Vec<GLenum> = Vec::with_capacity(max_logged_messages as usize);
|
||||
severities.set_len(max_logged_messages as usize);
|
||||
|
||||
let mut lengths: Vec<GLsizei> = Vec::with_capacity(max_logged_messages as usize);
|
||||
lengths.set_len(max_logged_messages as usize);
|
||||
|
||||
let message_count = gl::GetDebugMessageLog(
|
||||
max_logged_messages as u32,
|
||||
buffer_size,
|
||||
sources.as_mut_ptr(),
|
||||
types.as_mut_ptr(),
|
||||
ids.as_mut_ptr(),
|
||||
severities.as_mut_ptr(),
|
||||
lengths.as_mut_ptr(),
|
||||
message_buffer.as_mut_ptr(),
|
||||
);
|
||||
|
||||
if message_count == 0 {
|
||||
Log::writeln("Debug info is not available - run with OpenGL debug flag!".to_owned());
|
||||
}
|
||||
|
||||
let mut message = message_buffer.as_ptr();
|
||||
|
||||
for i in 0..message_count as usize {
|
||||
let source = sources[i];
|
||||
let ty = types[i];
|
||||
let severity = severities[i];
|
||||
let id = ids[i];
|
||||
let len = lengths[i] as usize;
|
||||
|
||||
let source_str =
|
||||
match source {
|
||||
gl::DEBUG_SOURCE_API => "API",
|
||||
gl::DEBUG_SOURCE_SHADER_COMPILER => "Shader Compiler",
|
||||
gl::DEBUG_SOURCE_WINDOW_SYSTEM => "Window System",
|
||||
gl::DEBUG_SOURCE_THIRD_PARTY => "Third Party",
|
||||
gl::DEBUG_SOURCE_APPLICATION => "Application",
|
||||
gl::DEBUG_SOURCE_OTHER => "Other",
|
||||
_ => "Unknown"
|
||||
};
|
||||
|
||||
let type_str =
|
||||
match ty {
|
||||
gl::DEBUG_TYPE_ERROR => "Error",
|
||||
gl::DEBUG_TYPE_DEPRECATED_BEHAVIOR => "Deprecated Behavior",
|
||||
gl::DEBUG_TYPE_UNDEFINED_BEHAVIOR => "Undefined Behavior",
|
||||
gl::DEBUG_TYPE_PERFORMANCE => "Performance",
|
||||
gl::DEBUG_TYPE_PORTABILITY => "Portability",
|
||||
gl::DEBUG_TYPE_OTHER => "Other",
|
||||
_ => "Unknown",
|
||||
};
|
||||
|
||||
let severity_str =
|
||||
match severity {
|
||||
gl::DEBUG_SEVERITY_HIGH => "High",
|
||||
gl::DEBUG_SEVERITY_MEDIUM => "Medium",
|
||||
gl::DEBUG_SEVERITY_LOW => "Low",
|
||||
gl::DEBUG_SEVERITY_NOTIFICATION => "Notification",
|
||||
_ => "Unknown"
|
||||
};
|
||||
|
||||
let str_msg = CStr::from_ptr(message);
|
||||
|
||||
Log::writeln(format!("OpenGL message\nSource: {}\nType: {}\nId: {}\nSeverity: {}\nMessage: {:?}\n",
|
||||
source_str,
|
||||
type_str,
|
||||
id,
|
||||
severity_str,
|
||||
str_msg));
|
||||
|
||||
message = message.add(len);
|
||||
}
|
||||
} else {
|
||||
Log::writeln("Debug info is not available - glGetDebugMessageLog is not available!".to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
use crate::{
|
||||
renderer::{
|
||||
framework::{
|
||||
framebuffer::{
|
||||
CullFace,
|
||||
DrawParameters,
|
||||
},
|
||||
gl::{
|
||||
self,
|
||||
types::{
|
||||
GLuint,
|
||||
GLboolean,
|
||||
GLenum,
|
||||
GLint
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
core::{
|
||||
math::Rect,
|
||||
color::Color,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct State {
|
||||
blend: bool,
|
||||
depth_test: bool,
|
||||
depth_write: bool,
|
||||
color_write: ColorMask,
|
||||
stencil_test: bool,
|
||||
cull_face: CullFace,
|
||||
culling: bool,
|
||||
stencil_mask: u32,
|
||||
clear_color: Color,
|
||||
clear_stencil: i32,
|
||||
clear_depth: f32,
|
||||
|
||||
framebuffer: GLuint,
|
||||
viewport: Rect<i32>,
|
||||
|
||||
blend_src_factor: GLuint,
|
||||
blend_dst_factor: GLuint,
|
||||
|
||||
program: GLuint,
|
||||
texture_units: [TextureUnit; 32],
|
||||
|
||||
stencil_func: StencilFunc,
|
||||
stencil_op: StencilOp,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct TextureUnit {
|
||||
target: GLenum,
|
||||
texture: GLuint,
|
||||
}
|
||||
|
||||
impl Default for TextureUnit {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
target: gl::TEXTURE_2D,
|
||||
texture: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn bool_to_gl_bool(v: bool) -> GLboolean {
|
||||
if v {
|
||||
gl::TRUE
|
||||
} else {
|
||||
gl::FALSE
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialOrd, PartialEq, Hash, Debug)]
|
||||
pub struct ColorMask {
|
||||
red: bool,
|
||||
green: bool,
|
||||
blue: bool,
|
||||
alpha: bool,
|
||||
}
|
||||
|
||||
impl Default for ColorMask {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
red: true,
|
||||
green: true,
|
||||
blue: true,
|
||||
alpha: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ColorMask {
|
||||
pub fn all(value: bool) -> Self {
|
||||
Self {
|
||||
red: value,
|
||||
green: value,
|
||||
blue: value,
|
||||
alpha: value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialOrd, PartialEq, Hash, Debug)]
|
||||
pub struct StencilFunc {
|
||||
pub func: GLenum,
|
||||
pub ref_value: GLint,
|
||||
pub mask: GLuint,
|
||||
}
|
||||
|
||||
impl Default for StencilFunc {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
func: gl::ALWAYS,
|
||||
ref_value: 0,
|
||||
mask: 0xFFFF_FFFF,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialOrd, PartialEq, Hash, Debug)]
|
||||
pub struct StencilOp {
|
||||
pub fail: GLenum,
|
||||
pub zfail: GLenum,
|
||||
pub zpass: GLenum,
|
||||
}
|
||||
|
||||
impl Default for StencilOp {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
fail: gl::KEEP,
|
||||
zfail: gl::KEEP,
|
||||
zpass: gl::KEEP,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
blend: false,
|
||||
depth_test: false,
|
||||
depth_write: true,
|
||||
color_write: Default::default(),
|
||||
stencil_test: false,
|
||||
cull_face: CullFace::Back,
|
||||
culling: false,
|
||||
stencil_mask: 0xFFFF_FFFF,
|
||||
clear_color: Color::from_rgba(0, 0, 0, 0),
|
||||
clear_stencil: 0,
|
||||
clear_depth: 1.0,
|
||||
framebuffer: 0,
|
||||
viewport: Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 1,
|
||||
h: 1,
|
||||
},
|
||||
blend_src_factor: gl::ONE,
|
||||
blend_dst_factor: gl::ZERO,
|
||||
program: 0,
|
||||
texture_units: [Default::default(); 32],
|
||||
stencil_func: Default::default(),
|
||||
stencil_op: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_framebuffer(&mut self, framebuffer: GLuint) {
|
||||
if self.framebuffer != framebuffer {
|
||||
self.framebuffer = framebuffer;
|
||||
|
||||
unsafe {
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_viewport(&mut self, viewport: Rect<i32>) {
|
||||
if self.viewport != viewport {
|
||||
self.viewport = viewport;
|
||||
|
||||
unsafe {
|
||||
gl::Viewport(self.viewport.x, self.viewport.y, self.viewport.w, self.viewport.h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_blend(&mut self, blend: bool) {
|
||||
if self.blend != blend {
|
||||
self.blend = blend;
|
||||
|
||||
unsafe {
|
||||
if self.blend {
|
||||
gl::Enable(gl::BLEND);
|
||||
} else {
|
||||
gl::Disable(gl::BLEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_depth_test(&mut self, depth_test: bool) {
|
||||
if self.depth_test != depth_test {
|
||||
self.depth_test = depth_test;
|
||||
|
||||
unsafe {
|
||||
if self.depth_test {
|
||||
gl::Enable(gl::DEPTH_TEST);
|
||||
} else {
|
||||
gl::Disable(gl::DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_depth_write(&mut self, depth_write: bool) {
|
||||
if self.depth_write != depth_write {
|
||||
self.depth_write = depth_write;
|
||||
|
||||
unsafe {
|
||||
gl::DepthMask(bool_to_gl_bool(self.depth_write));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_color_write(&mut self, color_write: ColorMask) {
|
||||
if self.color_write != color_write {
|
||||
self.color_write = color_write;
|
||||
|
||||
unsafe {
|
||||
gl::ColorMask(bool_to_gl_bool(self.color_write.red),
|
||||
bool_to_gl_bool(self.color_write.green),
|
||||
bool_to_gl_bool(self.color_write.blue),
|
||||
bool_to_gl_bool(self.color_write.alpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_stencil_test(&mut self, stencil_test: bool) {
|
||||
if self.stencil_test != stencil_test {
|
||||
self.stencil_test = stencil_test;
|
||||
|
||||
unsafe {
|
||||
if self.stencil_test {
|
||||
gl::Enable(gl::STENCIL_TEST);
|
||||
} else {
|
||||
gl::Disable(gl::STENCIL_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_cull_face(&mut self, cull_face: CullFace) {
|
||||
if self.cull_face != cull_face {
|
||||
self.cull_face = cull_face;
|
||||
|
||||
unsafe {
|
||||
gl::CullFace(self.cull_face.into_gl_value())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_culling(&mut self, culling: bool) {
|
||||
if self.culling != culling {
|
||||
self.culling = culling;
|
||||
|
||||
unsafe {
|
||||
if self.culling {
|
||||
gl::Enable(gl::CULL_FACE);
|
||||
} else {
|
||||
gl::Disable(gl::CULL_FACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_stencil_mask(&mut self, stencil_mask: u32) {
|
||||
if self.stencil_mask != stencil_mask {
|
||||
self.stencil_mask = stencil_mask;
|
||||
|
||||
unsafe {
|
||||
gl::StencilMask(stencil_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_clear_color(&mut self, color: Color) {
|
||||
if self.clear_color != color {
|
||||
self.clear_color = color;
|
||||
|
||||
let rgba = color.as_frgba();
|
||||
unsafe {
|
||||
gl::ClearColor(rgba.x, rgba.y, rgba.z, rgba.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_clear_depth(&mut self, depth: f32) {
|
||||
if self.clear_depth != depth {
|
||||
self.clear_depth = depth;
|
||||
|
||||
unsafe {
|
||||
gl::ClearDepth(depth as f64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_clear_stencil(&mut self, stencil: i32) {
|
||||
if self.clear_stencil != stencil {
|
||||
self.clear_stencil = stencil;
|
||||
|
||||
unsafe {
|
||||
gl::ClearStencil(stencil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_blend_func(&mut self, sfactor: GLenum, dfactor: GLenum) {
|
||||
if self.blend_src_factor != sfactor || self.blend_dst_factor != dfactor {
|
||||
self.blend_src_factor = sfactor;
|
||||
self.blend_dst_factor = dfactor;
|
||||
|
||||
unsafe {
|
||||
gl::BlendFunc(self.blend_src_factor, self.blend_dst_factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_program(&mut self, program: GLuint) {
|
||||
if self.program != program {
|
||||
self.program = program;
|
||||
|
||||
unsafe {
|
||||
gl::UseProgram(self.program);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_texture(&mut self, sampler_index: usize, target: GLenum, texture: GLuint) {
|
||||
let unit = self.texture_units.get_mut(sampler_index).unwrap();
|
||||
|
||||
if unit.target != target || unit.texture != texture {
|
||||
unit.texture = texture;
|
||||
unit.target = target;
|
||||
|
||||
unsafe {
|
||||
gl::ActiveTexture(gl::TEXTURE0 + sampler_index as u32);
|
||||
gl::BindTexture(target, texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_stencil_func(&mut self, func: StencilFunc) {
|
||||
if self.stencil_func != func {
|
||||
self.stencil_func = func;
|
||||
|
||||
unsafe {
|
||||
gl::StencilFunc(self.stencil_func.func, self.stencil_func.ref_value, self.stencil_func.mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_stencil_op(&mut self, op: StencilOp) {
|
||||
if self.stencil_op != op {
|
||||
self.stencil_op = op;
|
||||
|
||||
unsafe {
|
||||
gl::StencilOp(self.stencil_op.fail, self.stencil_op.zfail, self.stencil_op.zpass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invalidate_resource_bindings_cache(&mut self) {
|
||||
self.texture_units = Default::default();
|
||||
self.program = 0;
|
||||
}
|
||||
|
||||
pub fn apply_draw_parameters(&mut self, draw_params: &DrawParameters) {
|
||||
self.set_blend(draw_params.blend);
|
||||
self.set_depth_test(draw_params.depth_test);
|
||||
self.set_depth_write(draw_params.depth_write);
|
||||
self.set_color_write(draw_params.color_write);
|
||||
self.set_stencil_test(draw_params.stencil_test);
|
||||
self.set_cull_face(draw_params.cull_face);
|
||||
self.set_culling(draw_params.culling);
|
||||
}
|
||||
}
|
||||
+58
-47
@@ -4,29 +4,31 @@ use std::{
|
||||
};
|
||||
use crate::{
|
||||
renderer::{
|
||||
gpu_texture::{
|
||||
GpuTextureKind,
|
||||
PixelKind,
|
||||
GpuTexture,
|
||||
},
|
||||
framebuffer::{
|
||||
FrameBuffer,
|
||||
Attachment,
|
||||
AttachmentKind,
|
||||
CullFace,
|
||||
DrawParameters,
|
||||
FrameBufferTrait
|
||||
},
|
||||
gpu_program::{
|
||||
GpuProgram,
|
||||
UniformLocation,
|
||||
framework::{
|
||||
gpu_program::{
|
||||
GpuProgram,
|
||||
UniformLocation,
|
||||
UniformValue
|
||||
},
|
||||
framebuffer::{
|
||||
FrameBuffer,
|
||||
Attachment,
|
||||
AttachmentKind,
|
||||
CullFace,
|
||||
DrawParameters,
|
||||
FrameBufferTrait,
|
||||
},
|
||||
gpu_texture::{
|
||||
GpuTextureKind,
|
||||
PixelKind,
|
||||
GpuTexture,
|
||||
},
|
||||
state::State,
|
||||
},
|
||||
error::RendererError,
|
||||
RenderPassStatistics,
|
||||
TextureCache,
|
||||
GeometryCache,
|
||||
gpu_program::UniformValue,
|
||||
state::State
|
||||
},
|
||||
scene::{
|
||||
node::Node,
|
||||
@@ -60,12 +62,12 @@ impl GBufferShader {
|
||||
let vertex_source = include_str!("shaders/gbuffer_vs.glsl");
|
||||
let mut program = GpuProgram::from_source("GBufferShader", vertex_source, fragment_source)?;
|
||||
Ok(Self {
|
||||
world_matrix: program.get_uniform_location("worldMatrix")?,
|
||||
wvp_matrix: program.get_uniform_location("worldViewProjection")?,
|
||||
use_skeletal_animation: program.get_uniform_location("useSkeletalAnimation")?,
|
||||
bone_matrices: program.get_uniform_location("boneMatrices")?,
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture")?,
|
||||
normal_texture: program.get_uniform_location("normalTexture")?,
|
||||
world_matrix: program.uniform_location("worldMatrix")?,
|
||||
wvp_matrix: program.uniform_location("worldViewProjection")?,
|
||||
use_skeletal_animation: program.uniform_location("useSkeletalAnimation")?,
|
||||
bone_matrices: program.uniform_location("boneMatrices")?,
|
||||
diffuse_texture: program.uniform_location("diffuseTexture")?,
|
||||
normal_texture: program.uniform_location("normalTexture")?,
|
||||
program,
|
||||
})
|
||||
}
|
||||
@@ -82,7 +84,10 @@ pub struct GBuffer {
|
||||
|
||||
impl GBuffer {
|
||||
pub fn new(state: &mut State, width: usize, height: usize) -> Result<Self, RendererError> {
|
||||
let depth_stencil = Rc::new(RefCell::new(GpuTexture::new(GpuTextureKind::Rectangle { width, height }, PixelKind::D24S8, None)?));
|
||||
let depth_stencil = Rc::new(RefCell::new(GpuTexture::new(state, GpuTextureKind::Rectangle { width, height }, PixelKind::D24S8, None)?));
|
||||
|
||||
let diffuse_texture = GpuTexture::new(state, GpuTextureKind::Rectangle { width, height }, PixelKind::RGBA8, None)?;
|
||||
let normal_texture = GpuTexture::new(state, GpuTextureKind::Rectangle { width, height }, PixelKind::RGBA8, None)?;
|
||||
|
||||
let framebuffer = FrameBuffer::new(
|
||||
state,
|
||||
@@ -93,14 +98,16 @@ impl GBuffer {
|
||||
vec![
|
||||
Attachment {
|
||||
kind: AttachmentKind::Color,
|
||||
texture: Rc::new(RefCell::new(GpuTexture::new(GpuTextureKind::Rectangle { width, height }, PixelKind::RGBA8, None)?)),
|
||||
texture: Rc::new(RefCell::new(diffuse_texture)),
|
||||
},
|
||||
Attachment {
|
||||
kind: AttachmentKind::Color,
|
||||
texture: Rc::new(RefCell::new(GpuTexture::new(GpuTextureKind::Rectangle { width, height }, PixelKind::RGBA8, None)?)),
|
||||
texture: Rc::new(RefCell::new(normal_texture)),
|
||||
},
|
||||
])?;
|
||||
|
||||
let frame_texture = GpuTexture::new(state, GpuTextureKind::Rectangle { width, height }, PixelKind::RGBA8, None)?;
|
||||
|
||||
let opt_framebuffer = FrameBuffer::new(
|
||||
state,
|
||||
Attachment {
|
||||
@@ -110,7 +117,7 @@ impl GBuffer {
|
||||
vec![
|
||||
Attachment {
|
||||
kind: AttachmentKind::Color,
|
||||
texture: Rc::new(RefCell::new(GpuTexture::new(GpuTextureKind::Rectangle { width, height }, PixelKind::RGBA8, None)?)),
|
||||
texture: Rc::new(RefCell::new(frame_texture)),
|
||||
}
|
||||
])?;
|
||||
|
||||
@@ -182,6 +189,26 @@ impl GBuffer {
|
||||
};
|
||||
let mvp = view_projection * world;
|
||||
|
||||
let diffuse_texture = if let Some(texture) = surface.get_diffuse_texture() {
|
||||
if let Some(texture) = texture_cache.get(state, texture) {
|
||||
texture
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
};
|
||||
|
||||
let normal_texture = if let Some(texture) = surface.get_normal_texture() {
|
||||
if let Some(texture) = texture_cache.get(state, texture) {
|
||||
texture
|
||||
} else {
|
||||
normal_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
normal_dummy.clone()
|
||||
};
|
||||
|
||||
statistics.add_draw_call(
|
||||
self.framebuffer.draw(
|
||||
state,
|
||||
@@ -191,7 +218,7 @@ impl GBuffer {
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Back,
|
||||
culling: true,
|
||||
color_write: (true, true, true, true),
|
||||
color_write: Default::default(),
|
||||
depth_write: true,
|
||||
stencil_test: false,
|
||||
depth_test: true,
|
||||
@@ -200,27 +227,11 @@ impl GBuffer {
|
||||
&[
|
||||
(self.shader.diffuse_texture, UniformValue::Sampler {
|
||||
index: 0,
|
||||
texture: if let Some(texture) = surface.get_diffuse_texture() {
|
||||
if let Some(texture) = texture_cache.get(texture) {
|
||||
texture
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
},
|
||||
texture: diffuse_texture,
|
||||
}),
|
||||
(self.shader.normal_texture, UniformValue::Sampler {
|
||||
index: 1,
|
||||
texture: if let Some(texture) = surface.get_normal_texture() {
|
||||
if let Some(texture) = texture_cache.get(texture) {
|
||||
texture
|
||||
} else {
|
||||
normal_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
normal_dummy.clone()
|
||||
},
|
||||
texture: normal_texture,
|
||||
}),
|
||||
(self.shader.wvp_matrix, UniformValue::Mat4(mvp)),
|
||||
(self.shader.world_matrix, UniformValue::Mat4(world)),
|
||||
|
||||
+50
-152
@@ -1,25 +1,22 @@
|
||||
#[allow(clippy::all)]
|
||||
pub(in crate) mod gl;
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
pub mod surface;
|
||||
pub mod gpu_program;
|
||||
pub mod error;
|
||||
pub mod debug_renderer;
|
||||
|
||||
macro_rules! check_gl_error {
|
||||
() => (crate::renderer::check_gl_error_internal(line!(), file!()))
|
||||
}
|
||||
// Framework wraps all OpenGL calls so it has to be unsafe. Rest of renderer
|
||||
// code must be safe.
|
||||
#[macro_use]
|
||||
#[allow(unsafe_code)]
|
||||
mod framework;
|
||||
|
||||
mod geometry_buffer;
|
||||
mod ui_renderer;
|
||||
mod particle_system_renderer;
|
||||
mod gbuffer;
|
||||
mod deferred_light_renderer;
|
||||
mod shadow_map_renderer;
|
||||
mod flat_shader;
|
||||
mod gpu_texture;
|
||||
mod sprite_renderer;
|
||||
mod framebuffer;
|
||||
mod state;
|
||||
|
||||
use glutin::PossiblyCurrent;
|
||||
use std::{
|
||||
@@ -29,7 +26,6 @@ use std::{
|
||||
Mutex,
|
||||
},
|
||||
time,
|
||||
ffi::CStr,
|
||||
collections::HashMap,
|
||||
cell::RefCell,
|
||||
};
|
||||
@@ -45,26 +41,34 @@ use crate::{
|
||||
DeferredRendererContext,
|
||||
},
|
||||
error::RendererError,
|
||||
gpu_texture::{
|
||||
GpuTexture,
|
||||
GpuTextureKind,
|
||||
PixelKind,
|
||||
MininificationFilter,
|
||||
MagnificationFilter,
|
||||
framework::{
|
||||
gpu_texture::{
|
||||
GpuTexture,
|
||||
GpuTextureKind,
|
||||
PixelKind,
|
||||
MininificationFilter,
|
||||
MagnificationFilter,
|
||||
},
|
||||
geometry_buffer::{
|
||||
GeometryBuffer,
|
||||
GeometryBufferKind,
|
||||
ElementKind,
|
||||
AttributeKind,
|
||||
AttributeDefinition,
|
||||
},
|
||||
framebuffer::{
|
||||
BackBuffer,
|
||||
FrameBufferTrait,
|
||||
DrawParameters,
|
||||
CullFace,
|
||||
},
|
||||
gpu_program::UniformValue,
|
||||
state::State,
|
||||
gl
|
||||
},
|
||||
flat_shader::FlatShader,
|
||||
sprite_renderer::SpriteRenderer,
|
||||
gl::types::{GLsizei, GLenum, GLuint, GLchar},
|
||||
debug_renderer::DebugRenderer,
|
||||
geometry_buffer::{
|
||||
GeometryBuffer,
|
||||
GeometryBufferKind,
|
||||
ElementKind,
|
||||
AttributeKind,
|
||||
AttributeDefinition,
|
||||
},
|
||||
framebuffer::{BackBuffer, FrameBufferTrait, DrawParameters, CullFace},
|
||||
gpu_program::UniformValue,
|
||||
},
|
||||
scene::{
|
||||
SceneContainer,
|
||||
@@ -85,7 +89,6 @@ use crate::{
|
||||
gui::draw::DrawingContext,
|
||||
engine::resource_manager::TimedEntry,
|
||||
};
|
||||
use crate::renderer::state::State;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Statistics {
|
||||
@@ -296,7 +299,7 @@ pub struct TextureCache {
|
||||
}
|
||||
|
||||
impl TextureCache {
|
||||
fn get(&mut self, texture: Arc<Mutex<Texture>>) -> Option<Rc<RefCell<GpuTexture>>> {
|
||||
fn get(&mut self, state: &mut State, texture: Arc<Mutex<Texture>>) -> Option<Rc<RefCell<GpuTexture>>> {
|
||||
if texture.lock().unwrap().loaded {
|
||||
let key = (&*texture as *const _) as usize;
|
||||
let gpu_texture = self.map.entry(key).or_insert_with(move || {
|
||||
@@ -306,11 +309,12 @@ impl TextureCache {
|
||||
height: texture.height as usize,
|
||||
};
|
||||
let mut gpu_texture = GpuTexture::new(
|
||||
state,
|
||||
kind,
|
||||
PixelKind::from(texture.kind),
|
||||
Some(texture.bytes.as_slice()))
|
||||
.unwrap();
|
||||
gpu_texture.bind_mut(0)
|
||||
gpu_texture.bind_mut(state, 0)
|
||||
.generate_mip_maps()
|
||||
.set_minification_filter(MininificationFilter::LinearMip)
|
||||
.set_magnification_filter(MagnificationFilter::Linear)
|
||||
@@ -339,7 +343,9 @@ impl TextureCache {
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
pub(in crate) fn new(frame_size: (u32, u32)) -> Result<Self, RendererError> {
|
||||
pub(in crate) fn new(context: &mut glutin::WindowedContext<PossiblyCurrent>, frame_size: (u32, u32)) -> Result<Self, RendererError> {
|
||||
gl::load_with(|symbol| context.get_proc_address(symbol) as *const _);
|
||||
|
||||
let settings = QualitySettings::default();
|
||||
let mut state = State::new();
|
||||
|
||||
@@ -350,9 +356,9 @@ impl Renderer {
|
||||
flat_shader: FlatShader::new()?,
|
||||
statistics: Statistics::default(),
|
||||
sprite_renderer: SpriteRenderer::new()?,
|
||||
white_dummy: Rc::new(RefCell::new(GpuTexture::new(GpuTextureKind::Rectangle { width: 1, height: 1 },
|
||||
white_dummy: Rc::new(RefCell::new(GpuTexture::new(&mut state, GpuTextureKind::Rectangle { width: 1, height: 1 },
|
||||
PixelKind::RGBA8, Some(&[255, 255, 255, 255]))?)),
|
||||
normal_dummy: Rc::new(RefCell::new(GpuTexture::new(GpuTextureKind::Rectangle { width: 1, height: 1 },
|
||||
normal_dummy: Rc::new(RefCell::new(GpuTexture::new(&mut state, GpuTextureKind::Rectangle { width: 1, height: 1 },
|
||||
PixelKind::RGBA8, Some(&[128, 128, 255, 255]))?)),
|
||||
quad: SurfaceSharedData::make_unit_xy_quad(),
|
||||
ui_renderer: UiRenderer::new()?,
|
||||
@@ -364,7 +370,7 @@ impl Renderer {
|
||||
backbuffer_clear_color: Color::from_rgba(0, 0, 0, 0),
|
||||
texture_cache: Default::default(),
|
||||
geometry_cache: Default::default(),
|
||||
state
|
||||
state,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -416,6 +422,13 @@ impl Renderer {
|
||||
context: &glutin::WindowedContext<PossiblyCurrent>,
|
||||
dt: f32,
|
||||
) -> Result<(), RendererError> {
|
||||
// We have to invalidate resource bindings cache because some textures or programs,
|
||||
// or other GL resources can be destroyed and then on their "names" some new resource
|
||||
// are created, but cache still thinks that resource is correctly bound, but it is different
|
||||
// object have same name.
|
||||
self.state.invalidate_resource_bindings_cache();
|
||||
|
||||
// Update caches - this will remove timed out resources.
|
||||
self.geometry_cache.update(dt);
|
||||
self.texture_cache.update(dt);
|
||||
|
||||
@@ -444,10 +457,10 @@ impl Renderer {
|
||||
.entry(camera_handle)
|
||||
.and_modify(|buf| {
|
||||
if buf.width != viewport.w || buf.height != viewport.h {
|
||||
*buf = GBuffer::new(state,viewport.w as usize, viewport.h as usize).unwrap();
|
||||
*buf = GBuffer::new(state, viewport.w as usize, viewport.h as usize).unwrap();
|
||||
}
|
||||
})
|
||||
.or_insert_with(|| GBuffer::new(state,viewport.w as usize, viewport.h as usize).unwrap());
|
||||
.or_insert_with(|| GBuffer::new(state, viewport.w as usize, viewport.h as usize).unwrap());
|
||||
|
||||
self.statistics += gbuffer.fill(
|
||||
state,
|
||||
@@ -509,7 +522,7 @@ impl Renderer {
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Back,
|
||||
culling: false,
|
||||
color_write: (true, true, true, true),
|
||||
color_write: Default::default(),
|
||||
depth_write: true,
|
||||
stencil_test: false,
|
||||
depth_test: false,
|
||||
@@ -555,118 +568,3 @@ impl Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_gl_error_internal(line: u32, file: &str) {
|
||||
unsafe {
|
||||
let error_code = gl::GetError();
|
||||
if error_code != gl::NO_ERROR {
|
||||
let code = match error_code {
|
||||
gl::INVALID_ENUM => "GL_INVALID_ENUM",
|
||||
gl::INVALID_VALUE => "GL_INVALID_VALUE",
|
||||
gl::INVALID_OPERATION => "GL_INVALID_OPERATION",
|
||||
gl::STACK_OVERFLOW => "GL_STACK_OVERFLOW",
|
||||
gl::STACK_UNDERFLOW => "GL_STACK_UNDERFLOW",
|
||||
gl::OUT_OF_MEMORY => "GL_OUT_OF_MEMORY",
|
||||
_ => "Unknown",
|
||||
};
|
||||
|
||||
Log::writeln(format!("{} error has occurred! At line {} in file {}, stability is not guaranteed!", code, line, file));
|
||||
|
||||
if gl::GetDebugMessageLog::is_loaded() {
|
||||
let mut max_message_length = 0;
|
||||
gl::GetIntegerv(gl::MAX_DEBUG_MESSAGE_LENGTH, &mut max_message_length);
|
||||
|
||||
let mut max_logged_messages = 0;
|
||||
gl::GetIntegerv(gl::MAX_DEBUG_LOGGED_MESSAGES, &mut max_logged_messages);
|
||||
|
||||
let buffer_size = max_message_length * max_logged_messages;
|
||||
|
||||
let mut message_buffer: Vec<GLchar> = Vec::with_capacity(buffer_size as usize);
|
||||
message_buffer.set_len(buffer_size as usize);
|
||||
|
||||
let mut sources: Vec<GLenum> = Vec::with_capacity(max_logged_messages as usize);
|
||||
sources.set_len(max_logged_messages as usize);
|
||||
|
||||
let mut types: Vec<GLenum> = Vec::with_capacity(max_logged_messages as usize);
|
||||
types.set_len(max_logged_messages as usize);
|
||||
|
||||
let mut ids: Vec<GLuint> = Vec::with_capacity(max_logged_messages as usize);
|
||||
ids.set_len(max_logged_messages as usize);
|
||||
|
||||
let mut severities: Vec<GLenum> = Vec::with_capacity(max_logged_messages as usize);
|
||||
severities.set_len(max_logged_messages as usize);
|
||||
|
||||
let mut lengths: Vec<GLsizei> = Vec::with_capacity(max_logged_messages as usize);
|
||||
lengths.set_len(max_logged_messages as usize);
|
||||
|
||||
let message_count = gl::GetDebugMessageLog(
|
||||
max_logged_messages as u32,
|
||||
buffer_size,
|
||||
sources.as_mut_ptr(),
|
||||
types.as_mut_ptr(),
|
||||
ids.as_mut_ptr(),
|
||||
severities.as_mut_ptr(),
|
||||
lengths.as_mut_ptr(),
|
||||
message_buffer.as_mut_ptr(),
|
||||
);
|
||||
|
||||
if message_count == 0 {
|
||||
Log::writeln("Debug info is not available - run with OpenGL debug flag!".to_owned());
|
||||
}
|
||||
|
||||
let mut message = message_buffer.as_ptr();
|
||||
|
||||
for i in 0..message_count as usize {
|
||||
let source = sources[i];
|
||||
let ty = types[i];
|
||||
let severity = severities[i];
|
||||
let id = ids[i];
|
||||
let len = lengths[i] as usize;
|
||||
|
||||
let source_str =
|
||||
match source {
|
||||
gl::DEBUG_SOURCE_API => "API",
|
||||
gl::DEBUG_SOURCE_SHADER_COMPILER => "Shader Compiler",
|
||||
gl::DEBUG_SOURCE_WINDOW_SYSTEM => "Window System",
|
||||
gl::DEBUG_SOURCE_THIRD_PARTY => "Third Party",
|
||||
gl::DEBUG_SOURCE_APPLICATION => "Application",
|
||||
gl::DEBUG_SOURCE_OTHER => "Other",
|
||||
_ => "Unknown"
|
||||
};
|
||||
|
||||
let type_str =
|
||||
match ty {
|
||||
gl::DEBUG_TYPE_ERROR => "Error",
|
||||
gl::DEBUG_TYPE_DEPRECATED_BEHAVIOR => "Deprecated Behavior",
|
||||
gl::DEBUG_TYPE_UNDEFINED_BEHAVIOR => "Undefined Behavior",
|
||||
gl::DEBUG_TYPE_PERFORMANCE => "Performance",
|
||||
gl::DEBUG_TYPE_PORTABILITY => "Portability",
|
||||
gl::DEBUG_TYPE_OTHER => "Other",
|
||||
_ => "Unknown",
|
||||
};
|
||||
|
||||
let severity_str =
|
||||
match severity {
|
||||
gl::DEBUG_SEVERITY_HIGH => "High",
|
||||
gl::DEBUG_SEVERITY_MEDIUM => "Medium",
|
||||
gl::DEBUG_SEVERITY_LOW => "Low",
|
||||
gl::DEBUG_SEVERITY_NOTIFICATION => "Notification",
|
||||
_ => "Unknown"
|
||||
};
|
||||
|
||||
let str_msg = CStr::from_ptr(message);
|
||||
|
||||
Log::writeln(format!("OpenGL message\nSource: {}\nType: {}\nId: {}\nSeverity: {}\nMessage: {:?}\n",
|
||||
source_str,
|
||||
type_str,
|
||||
id,
|
||||
severity_str,
|
||||
str_msg));
|
||||
|
||||
message = message.add(len);
|
||||
}
|
||||
} else {
|
||||
Log::writeln("Debug info is not available - glGetDebugMessageLog is not available!".to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,4 @@
|
||||
use crate::{
|
||||
renderer::{
|
||||
geometry_buffer::{
|
||||
GeometryBuffer,
|
||||
GeometryBufferKind,
|
||||
AttributeDefinition,
|
||||
AttributeKind,
|
||||
ElementKind,
|
||||
},
|
||||
gl,
|
||||
gpu_program::{GpuProgram, UniformLocation},
|
||||
error::RendererError,
|
||||
gpu_texture::GpuTexture,
|
||||
RenderPassStatistics,
|
||||
},
|
||||
scene::{
|
||||
node::Node,
|
||||
particle_system,
|
||||
@@ -24,13 +10,39 @@ use crate::{
|
||||
vec2::Vec2,
|
||||
Rect,
|
||||
},
|
||||
renderer::{
|
||||
error::RendererError,
|
||||
framework::{
|
||||
gpu_texture::GpuTexture,
|
||||
gpu_program::{
|
||||
GpuProgram,
|
||||
UniformLocation,
|
||||
UniformValue,
|
||||
},
|
||||
gl,
|
||||
geometry_buffer::{
|
||||
GeometryBuffer,
|
||||
GeometryBufferKind,
|
||||
AttributeDefinition,
|
||||
AttributeKind,
|
||||
ElementKind,
|
||||
},
|
||||
framebuffer::{
|
||||
FrameBuffer,
|
||||
DrawParameters,
|
||||
CullFace,
|
||||
FrameBufferTrait,
|
||||
},
|
||||
state::State
|
||||
},
|
||||
RenderPassStatistics,
|
||||
TextureCache,
|
||||
},
|
||||
};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
rc::Rc,
|
||||
};
|
||||
use crate::renderer::TextureCache;
|
||||
use crate::renderer::gpu_program::UniformValue;
|
||||
use crate::renderer::framebuffer::{FrameBuffer, DrawParameters, CullFace, FrameBufferTrait};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use crate::renderer::state::State;
|
||||
|
||||
struct ParticleSystemShader {
|
||||
program: GpuProgram,
|
||||
@@ -50,14 +62,14 @@ impl ParticleSystemShader {
|
||||
let fragment_source = include_str!("shaders/particle_system_fs.glsl");
|
||||
let mut program = GpuProgram::from_source("ParticleSystemShader", vertex_source, fragment_source)?;
|
||||
Ok(Self {
|
||||
view_projection_matrix: program.get_uniform_location("viewProjectionMatrix")?,
|
||||
world_matrix: program.get_uniform_location("worldMatrix")?,
|
||||
camera_side_vector: program.get_uniform_location("cameraSideVector")?,
|
||||
camera_up_vector: program.get_uniform_location("cameraUpVector")?,
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture")?,
|
||||
depth_buffer_texture: program.get_uniform_location("depthBufferTexture")?,
|
||||
inv_screen_size: program.get_uniform_location("invScreenSize")?,
|
||||
proj_params: program.get_uniform_location("projParams")?,
|
||||
view_projection_matrix: program.uniform_location("viewProjectionMatrix")?,
|
||||
world_matrix: program.uniform_location("worldMatrix")?,
|
||||
camera_side_vector: program.uniform_location("cameraSideVector")?,
|
||||
camera_up_vector: program.uniform_location("cameraUpVector")?,
|
||||
diffuse_texture: program.uniform_location("diffuseTexture")?,
|
||||
depth_buffer_texture: program.uniform_location("depthBufferTexture")?,
|
||||
inv_screen_size: program.uniform_location("invScreenSize")?,
|
||||
proj_params: program.uniform_location("projParams")?,
|
||||
program,
|
||||
})
|
||||
}
|
||||
@@ -106,9 +118,7 @@ impl ParticleSystemRenderer {
|
||||
) -> RenderPassStatistics {
|
||||
let mut statistics = RenderPassStatistics::default();
|
||||
|
||||
unsafe {
|
||||
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
state.set_blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
let inv_view = camera.inv_view_matrix().unwrap();
|
||||
|
||||
@@ -131,49 +141,49 @@ impl ParticleSystemRenderer {
|
||||
.set_triangles(self.draw_data.get_triangles())
|
||||
.set_vertices(self.draw_data.get_vertices());
|
||||
|
||||
let uniforms = [
|
||||
(self.shader.depth_buffer_texture, UniformValue::Sampler { index: 0, texture: depth.clone() }),
|
||||
(self.shader.diffuse_texture, UniformValue::Sampler {
|
||||
index: 1,
|
||||
texture: if let Some(texture) = particle_system.texture() {
|
||||
if let Some(texture) = texture_cache.get(state,texture) {
|
||||
texture
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
},
|
||||
}),
|
||||
(self.shader.camera_side_vector, UniformValue::Vec3(camera_side)),
|
||||
(self.shader.camera_up_vector, UniformValue::Vec3(camera_up)),
|
||||
(self.shader.view_projection_matrix, UniformValue::Mat4(camera.view_projection_matrix())),
|
||||
(self.shader.world_matrix, UniformValue::Mat4(node.base().global_transform())),
|
||||
(self.shader.inv_screen_size, UniformValue::Vec2(Vec2::new(1.0 / frame_width, 1.0 / frame_height))),
|
||||
(self.shader.proj_params, UniformValue::Vec2(Vec2::new(camera.z_far(), camera.z_near())))
|
||||
];
|
||||
|
||||
let draw_params = DrawParameters {
|
||||
cull_face: CullFace::Front,
|
||||
culling: false,
|
||||
color_write: Default::default(),
|
||||
depth_write: false,
|
||||
stencil_test: false,
|
||||
depth_test: true,
|
||||
blend: true,
|
||||
};
|
||||
|
||||
statistics.add_draw_call(
|
||||
framebuffer.draw(
|
||||
state,
|
||||
viewport,
|
||||
&mut self.geometry_buffer,
|
||||
&mut self.shader.program,
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Front,
|
||||
culling: false,
|
||||
color_write: (true, true, true, true),
|
||||
depth_write: false,
|
||||
stencil_test: false,
|
||||
depth_test: true,
|
||||
blend: true,
|
||||
},
|
||||
&[
|
||||
(self.shader.depth_buffer_texture, UniformValue::Sampler { index: 0, texture: depth.clone() }),
|
||||
(self.shader.diffuse_texture, UniformValue::Sampler {
|
||||
index: 1,
|
||||
texture: if let Some(texture) = particle_system.texture() {
|
||||
if let Some(texture) = texture_cache.get(texture) {
|
||||
texture
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
},
|
||||
}),
|
||||
(self.shader.camera_side_vector, UniformValue::Vec3(camera_side)),
|
||||
(self.shader.camera_up_vector, UniformValue::Vec3(camera_up)),
|
||||
(self.shader.view_projection_matrix, UniformValue::Mat4(camera.view_projection_matrix())),
|
||||
(self.shader.world_matrix, UniformValue::Mat4(node.base().global_transform())),
|
||||
(self.shader.inv_screen_size, UniformValue::Vec2(Vec2::new(1.0 / frame_width, 1.0 / frame_height))),
|
||||
(self.shader.proj_params, UniformValue::Vec2(Vec2::new(camera.z_far(), camera.z_near())))],
|
||||
draw_params,
|
||||
&uniforms,
|
||||
));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
gl::Disable(gl::BLEND);
|
||||
gl::DepthMask(gl::TRUE);
|
||||
}
|
||||
|
||||
statistics
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,31 +3,6 @@ use std::{
|
||||
rc::Rc,
|
||||
};
|
||||
use crate::{
|
||||
renderer::{
|
||||
gpu_texture::{
|
||||
GpuTextureKind,
|
||||
PixelKind,
|
||||
MagnificationFilter,
|
||||
MininificationFilter,
|
||||
Coordinate,
|
||||
WrapMode,
|
||||
CubeMapFace,
|
||||
GpuTexture,
|
||||
},
|
||||
framebuffer::{
|
||||
FrameBuffer,
|
||||
Attachment,
|
||||
AttachmentKind,
|
||||
},
|
||||
gpu_program::{
|
||||
GpuProgram,
|
||||
UniformLocation,
|
||||
},
|
||||
TextureCache,
|
||||
GeometryCache,
|
||||
RenderPassStatistics,
|
||||
error::RendererError,
|
||||
},
|
||||
scene::{
|
||||
node::Node,
|
||||
graph::Graph,
|
||||
@@ -42,10 +17,39 @@ use crate::{
|
||||
},
|
||||
color::Color,
|
||||
},
|
||||
renderer::{
|
||||
framework::{
|
||||
framebuffer::{
|
||||
DrawParameters,
|
||||
CullFace,
|
||||
FrameBufferTrait,
|
||||
FrameBuffer,
|
||||
Attachment,
|
||||
AttachmentKind
|
||||
},
|
||||
gpu_program::{
|
||||
UniformValue,
|
||||
GpuProgram,
|
||||
UniformLocation
|
||||
},
|
||||
gpu_texture::{
|
||||
GpuTextureKind,
|
||||
PixelKind,
|
||||
MagnificationFilter,
|
||||
MininificationFilter,
|
||||
Coordinate,
|
||||
WrapMode,
|
||||
CubeMapFace,
|
||||
GpuTexture,
|
||||
},
|
||||
state::{State, ColorMask}
|
||||
},
|
||||
TextureCache,
|
||||
GeometryCache,
|
||||
RenderPassStatistics,
|
||||
error::RendererError,
|
||||
}
|
||||
};
|
||||
use crate::renderer::framebuffer::{DrawParameters, CullFace, FrameBufferTrait};
|
||||
use crate::renderer::gpu_program::UniformValue;
|
||||
use crate::renderer::state::State;
|
||||
|
||||
struct SpotShadowMapShader {
|
||||
program: GpuProgram,
|
||||
@@ -61,10 +65,10 @@ impl SpotShadowMapShader {
|
||||
let vertex_source = include_str!("shaders/spot_shadow_map_vs.glsl");
|
||||
let mut program = GpuProgram::from_source("SpotShadowMapShader", vertex_source, fragment_source)?;
|
||||
Ok(Self {
|
||||
bone_matrices: program.get_uniform_location("boneMatrices")?,
|
||||
world_view_projection_matrix: program.get_uniform_location("worldViewProjection")?,
|
||||
use_skeletal_animation: program.get_uniform_location("useSkeletalAnimation")?,
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture")?,
|
||||
bone_matrices: program.uniform_location("boneMatrices")?,
|
||||
world_view_projection_matrix: program.uniform_location("worldViewProjection")?,
|
||||
use_skeletal_animation: program.uniform_location("useSkeletalAnimation")?,
|
||||
diffuse_texture: program.uniform_location("diffuseTexture")?,
|
||||
|
||||
program,
|
||||
})
|
||||
@@ -80,21 +84,23 @@ pub struct SpotShadowMapRenderer {
|
||||
|
||||
impl SpotShadowMapRenderer {
|
||||
pub fn new(state: &mut State, size: usize) -> Result<Self, RendererError> {
|
||||
let depth = {
|
||||
let kind = GpuTextureKind::Rectangle { width: size, height: size };
|
||||
let mut texture = GpuTexture::new(state, kind, PixelKind::D32, None)?;
|
||||
texture.bind_mut(state, 0)
|
||||
.set_magnification_filter(MagnificationFilter::Linear)
|
||||
.set_minification_filter(MininificationFilter::Linear)
|
||||
.set_wrap(Coordinate::T, WrapMode::ClampToBorder)
|
||||
.set_wrap(Coordinate::S, WrapMode::ClampToBorder)
|
||||
.set_border_color(Color::WHITE);
|
||||
texture
|
||||
};
|
||||
|
||||
let framebuffer = FrameBuffer::new(
|
||||
state,
|
||||
Attachment {
|
||||
kind: AttachmentKind::Depth,
|
||||
texture: Rc::new(RefCell::new({
|
||||
let kind = GpuTextureKind::Rectangle { width: size, height: size };
|
||||
let mut texture = GpuTexture::new(kind, PixelKind::D32, None)?;
|
||||
texture.bind_mut(0)
|
||||
.set_magnification_filter(MagnificationFilter::Linear)
|
||||
.set_minification_filter(MininificationFilter::Linear)
|
||||
.set_wrap(Coordinate::T, WrapMode::ClampToBorder)
|
||||
.set_wrap(Coordinate::S, WrapMode::ClampToBorder)
|
||||
.set_border_color(Color::WHITE);
|
||||
texture
|
||||
})),
|
||||
texture: Rc::new(RefCell::new(depth)),
|
||||
},
|
||||
vec![])?;
|
||||
|
||||
@@ -147,6 +153,16 @@ impl SpotShadowMapRenderer {
|
||||
};
|
||||
let mvp = *light_view_projection * world;
|
||||
|
||||
let diffuse_texture = if let Some(texture) = surface.get_diffuse_texture() {
|
||||
if let Some(texture) = textures.get(state, texture) {
|
||||
texture
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
};
|
||||
|
||||
statistics.add_draw_call(self.framebuffer.draw(
|
||||
state,
|
||||
viewport,
|
||||
@@ -155,7 +171,7 @@ impl SpotShadowMapRenderer {
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Back,
|
||||
culling: true,
|
||||
color_write: (false, false, false, false),
|
||||
color_write: ColorMask::all(false),
|
||||
depth_write: true,
|
||||
stencil_test: false,
|
||||
depth_test: true,
|
||||
@@ -178,15 +194,7 @@ impl SpotShadowMapRenderer {
|
||||
})),
|
||||
(self.shader.diffuse_texture, UniformValue::Sampler {
|
||||
index: 0,
|
||||
texture: if let Some(texture) = surface.get_diffuse_texture() {
|
||||
if let Some(texture) = textures.get(texture) {
|
||||
texture
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
},
|
||||
texture: diffuse_texture,
|
||||
})
|
||||
],
|
||||
));
|
||||
@@ -214,12 +222,12 @@ impl PointShadowMapShader {
|
||||
let vertex_source = include_str!("shaders/point_shadow_map_vs.glsl");
|
||||
let mut program = GpuProgram::from_source("PointShadowMapShader", vertex_source, fragment_source)?;
|
||||
Ok(Self {
|
||||
world_matrix: program.get_uniform_location("worldMatrix")?,
|
||||
bone_matrices: program.get_uniform_location("boneMatrices")?,
|
||||
world_view_projection_matrix: program.get_uniform_location("worldViewProjection")?,
|
||||
use_skeletal_animation: program.get_uniform_location("useSkeletalAnimation")?,
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture")?,
|
||||
light_position: program.get_uniform_location("lightPosition")?,
|
||||
world_matrix: program.uniform_location("worldMatrix")?,
|
||||
bone_matrices: program.uniform_location("boneMatrices")?,
|
||||
world_view_projection_matrix: program.uniform_location("worldViewProjection")?,
|
||||
use_skeletal_animation: program.uniform_location("useSkeletalAnimation")?,
|
||||
diffuse_texture: program.uniform_location("diffuseTexture")?,
|
||||
light_position: program.uniform_location("lightPosition")?,
|
||||
program,
|
||||
})
|
||||
}
|
||||
@@ -273,35 +281,39 @@ impl PointShadowMapRenderer {
|
||||
];
|
||||
|
||||
pub fn new(state: &mut State, size: usize) -> Result<PointShadowMapRenderer, RendererError> {
|
||||
let depth = {
|
||||
let kind = GpuTextureKind::Rectangle { width: size, height: size };
|
||||
let mut texture = GpuTexture::new(state, kind, PixelKind::D32, None)?;
|
||||
texture.bind_mut(state, 0)
|
||||
.set_minification_filter(MininificationFilter::Nearest)
|
||||
.set_magnification_filter(MagnificationFilter::Nearest)
|
||||
.set_wrap(Coordinate::S, WrapMode::ClampToEdge)
|
||||
.set_wrap(Coordinate::T, WrapMode::ClampToEdge);
|
||||
texture
|
||||
};
|
||||
|
||||
let cube_map = {
|
||||
let kind = GpuTextureKind::Cube { width: size, height: size };
|
||||
let mut texture = GpuTexture::new(state, kind, PixelKind::F32, None)?;
|
||||
texture.bind_mut(state, 0)
|
||||
.set_minification_filter(MininificationFilter::Linear)
|
||||
.set_magnification_filter(MagnificationFilter::Linear)
|
||||
.set_wrap(Coordinate::S, WrapMode::ClampToBorder)
|
||||
.set_wrap(Coordinate::T, WrapMode::ClampToBorder)
|
||||
.set_border_color(Color::WHITE);
|
||||
texture
|
||||
};
|
||||
|
||||
let framebuffer = FrameBuffer::new(
|
||||
state,
|
||||
Attachment {
|
||||
kind: AttachmentKind::Depth,
|
||||
texture: Rc::new(RefCell::new({
|
||||
let kind = GpuTextureKind::Rectangle { width: size, height: size };
|
||||
let mut texture = GpuTexture::new(kind, PixelKind::D32, None)?;
|
||||
texture.bind_mut(0)
|
||||
.set_minification_filter(MininificationFilter::Nearest)
|
||||
.set_magnification_filter(MagnificationFilter::Nearest)
|
||||
.set_wrap(Coordinate::S, WrapMode::ClampToEdge)
|
||||
.set_wrap(Coordinate::T, WrapMode::ClampToEdge);
|
||||
texture
|
||||
})),
|
||||
texture: Rc::new(RefCell::new(depth)),
|
||||
},
|
||||
vec![
|
||||
Attachment {
|
||||
kind: AttachmentKind::Color,
|
||||
texture: Rc::new(RefCell::new({
|
||||
let kind = GpuTextureKind::Cube { width: size, height: size };
|
||||
let mut texture = GpuTexture::new(kind, PixelKind::F32, None)?;
|
||||
texture.bind_mut(0)
|
||||
.set_minification_filter(MininificationFilter::Linear)
|
||||
.set_magnification_filter(MagnificationFilter::Linear)
|
||||
.set_wrap(Coordinate::S, WrapMode::ClampToBorder)
|
||||
.set_wrap(Coordinate::T, WrapMode::ClampToBorder)
|
||||
.set_border_color(Color::WHITE);
|
||||
texture
|
||||
})),
|
||||
texture: Rc::new(RefCell::new(cube_map)),
|
||||
}
|
||||
])?;
|
||||
|
||||
@@ -365,6 +377,16 @@ impl PointShadowMapRenderer {
|
||||
};
|
||||
let mvp = light_view_projection_matrix * world;
|
||||
|
||||
let diffuse_texture = if let Some(texture) = surface.get_diffuse_texture() {
|
||||
if let Some(texture) = texture_cache.get(state, texture) {
|
||||
texture
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
};
|
||||
|
||||
statistics.add_draw_call(self.framebuffer.draw(
|
||||
state,
|
||||
viewport,
|
||||
@@ -373,7 +395,7 @@ impl PointShadowMapRenderer {
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Back,
|
||||
culling: true,
|
||||
color_write: (true, true, true, true),
|
||||
color_write: Default::default(),
|
||||
depth_write: true,
|
||||
stencil_test: false,
|
||||
depth_test: true,
|
||||
@@ -398,15 +420,7 @@ impl PointShadowMapRenderer {
|
||||
})),
|
||||
(self.shader.diffuse_texture, UniformValue::Sampler {
|
||||
index: 0,
|
||||
texture: if let Some(texture) = surface.get_diffuse_texture() {
|
||||
if let Some(texture) = texture_cache.get(texture) {
|
||||
texture
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
},
|
||||
texture: diffuse_texture,
|
||||
})
|
||||
],
|
||||
));
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
use crate::{
|
||||
renderer::{
|
||||
surface::SurfaceSharedData,
|
||||
gpu_program::{GpuProgram, UniformLocation},
|
||||
error::RendererError,
|
||||
gl,
|
||||
gpu_texture::GpuTexture,
|
||||
RenderPassStatistics,
|
||||
},
|
||||
scene::{
|
||||
node::Node,
|
||||
base::AsBase,
|
||||
@@ -14,17 +6,36 @@ use crate::{
|
||||
camera::Camera,
|
||||
},
|
||||
core::{
|
||||
math::{
|
||||
Rect,
|
||||
math::Rect,
|
||||
},
|
||||
renderer::{
|
||||
TextureCache,
|
||||
GeometryCache,
|
||||
surface::SurfaceSharedData,
|
||||
error::RendererError,
|
||||
framework::{
|
||||
gpu_texture::GpuTexture,
|
||||
gl,
|
||||
gpu_program::{
|
||||
UniformValue,
|
||||
GpuProgram,
|
||||
UniformLocation,
|
||||
},
|
||||
framebuffer::{
|
||||
FrameBuffer,
|
||||
DrawParameters,
|
||||
CullFace,
|
||||
FrameBufferTrait,
|
||||
},
|
||||
state::State
|
||||
},
|
||||
RenderPassStatistics,
|
||||
},
|
||||
};
|
||||
use crate::renderer::{TextureCache, GeometryCache};
|
||||
use crate::renderer::gpu_program::{UniformValue};
|
||||
use crate::renderer::framebuffer::{FrameBuffer, DrawParameters, CullFace, FrameBufferTrait};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use crate::renderer::state::State;
|
||||
use std::{
|
||||
rc::Rc,
|
||||
cell::RefCell,
|
||||
};
|
||||
|
||||
struct SpriteShader {
|
||||
program: GpuProgram,
|
||||
@@ -44,14 +55,14 @@ impl SpriteShader {
|
||||
let vertex_source = include_str!("shaders/sprite_vs.glsl");
|
||||
let mut program = GpuProgram::from_source("FlatShader", vertex_source, fragment_source)?;
|
||||
Ok(Self {
|
||||
view_projection_matrix: program.get_uniform_location("viewProjectionMatrix")?,
|
||||
world_matrix: program.get_uniform_location("worldMatrix")?,
|
||||
camera_side_vector: program.get_uniform_location("cameraSideVector")?,
|
||||
camera_up_vector: program.get_uniform_location("cameraUpVector")?,
|
||||
size: program.get_uniform_location("size")?,
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture")?,
|
||||
color: program.get_uniform_location("color")?,
|
||||
rotation: program.get_uniform_location("rotation")?,
|
||||
view_projection_matrix: program.uniform_location("viewProjectionMatrix")?,
|
||||
world_matrix: program.uniform_location("worldMatrix")?,
|
||||
camera_side_vector: program.uniform_location("cameraSideVector")?,
|
||||
camera_up_vector: program.uniform_location("cameraUpVector")?,
|
||||
size: program.uniform_location("size")?,
|
||||
diffuse_texture: program.uniform_location("diffuseTexture")?,
|
||||
color: program.uniform_location("color")?,
|
||||
rotation: program.uniform_location("rotation")?,
|
||||
|
||||
program,
|
||||
})
|
||||
@@ -86,9 +97,7 @@ impl SpriteRenderer {
|
||||
) -> RenderPassStatistics {
|
||||
let mut statistics = RenderPassStatistics::default();
|
||||
|
||||
unsafe {
|
||||
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
state.set_blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
let inv_view = camera.inv_view_matrix().unwrap();
|
||||
|
||||
@@ -102,6 +111,16 @@ impl SpriteRenderer {
|
||||
continue;
|
||||
};
|
||||
|
||||
let diffuse_texture = if let Some(texture) = sprite.texture() {
|
||||
if let Some(texture) = textures.get(state, texture) {
|
||||
texture
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
};
|
||||
|
||||
statistics.add_draw_call(framebuffer.draw(
|
||||
state,
|
||||
viewport,
|
||||
@@ -110,7 +129,7 @@ impl SpriteRenderer {
|
||||
DrawParameters {
|
||||
cull_face: CullFace::Back,
|
||||
culling: true,
|
||||
color_write: (true, true, true, true),
|
||||
color_write: Default::default(),
|
||||
depth_write: false,
|
||||
stencil_test: false,
|
||||
depth_test: true,
|
||||
@@ -119,15 +138,7 @@ impl SpriteRenderer {
|
||||
&[
|
||||
(self.shader.diffuse_texture, UniformValue::Sampler {
|
||||
index: 0,
|
||||
texture: if let Some(texture) = sprite.texture() {
|
||||
if let Some(texture) = textures.get(texture) {
|
||||
texture
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
} else {
|
||||
white_dummy.clone()
|
||||
}
|
||||
texture: diffuse_texture,
|
||||
}),
|
||||
(self.shader.view_projection_matrix, UniformValue::Mat4(camera.view_projection_matrix())),
|
||||
(self.shader.world_matrix, UniformValue::Mat4(node.base().global_transform())),
|
||||
@@ -136,7 +147,7 @@ impl SpriteRenderer {
|
||||
(self.shader.size, UniformValue::Float(sprite.size())),
|
||||
(self.shader.color, UniformValue::Color(sprite.color())),
|
||||
(self.shader.rotation, UniformValue::Float(sprite.rotation()))
|
||||
]
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,246 +0,0 @@
|
||||
use crate::{
|
||||
renderer::{
|
||||
framebuffer::{
|
||||
CullFace,
|
||||
DrawParameters,
|
||||
},
|
||||
gl::{
|
||||
self,
|
||||
types::{
|
||||
GLuint,
|
||||
GLboolean,
|
||||
GLenum
|
||||
}
|
||||
}
|
||||
},
|
||||
core::{
|
||||
math::Rect,
|
||||
color::Color
|
||||
}
|
||||
};
|
||||
|
||||
pub struct State {
|
||||
blend: bool,
|
||||
depth_test: bool,
|
||||
depth_write: bool,
|
||||
color_write: (bool, bool, bool, bool),
|
||||
stencil_test: bool,
|
||||
cull_face: CullFace,
|
||||
culling: bool,
|
||||
stencil_mask: u32,
|
||||
clear_color: Color,
|
||||
clear_stencil: i32,
|
||||
clear_depth: f32,
|
||||
|
||||
framebuffer: GLuint,
|
||||
viewport: Rect<i32>,
|
||||
|
||||
blend_src_factor: GLuint,
|
||||
blend_dst_factor: GLuint,
|
||||
}
|
||||
|
||||
fn bool_to_gl_bool(v: bool) -> GLboolean {
|
||||
if v {
|
||||
gl::TRUE
|
||||
} else {
|
||||
gl::FALSE
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
blend: false,
|
||||
depth_test: false,
|
||||
depth_write: true,
|
||||
color_write: (true, true, true, true),
|
||||
stencil_test: false,
|
||||
cull_face: CullFace::Back,
|
||||
culling: false,
|
||||
stencil_mask: 0xFFFF_FFFF,
|
||||
clear_color: Color::from_rgba(0, 0, 0, 0),
|
||||
clear_stencil: 0,
|
||||
clear_depth: 1.0,
|
||||
framebuffer: 0,
|
||||
viewport: Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 1,
|
||||
h: 1,
|
||||
},
|
||||
blend_src_factor: gl::ONE,
|
||||
blend_dst_factor: gl::ZERO
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_framebuffer(&mut self, framebuffer: GLuint) {
|
||||
unsafe {
|
||||
if self.framebuffer != framebuffer {
|
||||
self.framebuffer = framebuffer;
|
||||
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_viewport(&mut self, viewport: Rect<i32>) {
|
||||
unsafe {
|
||||
if self.viewport != viewport {
|
||||
self.viewport = viewport;
|
||||
|
||||
gl::Viewport(self.viewport.x, self.viewport.y, self.viewport.w, self.viewport.h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_blend(&mut self, blend: bool) {
|
||||
unsafe {
|
||||
if self.blend != blend {
|
||||
self.blend = blend;
|
||||
|
||||
if self.blend {
|
||||
gl::Enable(gl::BLEND);
|
||||
} else {
|
||||
gl::Disable(gl::BLEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_depth_test(&mut self, depth_test: bool) {
|
||||
unsafe {
|
||||
if self.depth_test != depth_test {
|
||||
self.depth_test = depth_test;
|
||||
|
||||
if self.depth_test {
|
||||
gl::Enable(gl::DEPTH_TEST);
|
||||
} else {
|
||||
gl::Disable(gl::DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_depth_write(&mut self, depth_write: bool) {
|
||||
unsafe {
|
||||
if self.depth_write != depth_write {
|
||||
self.depth_write = depth_write;
|
||||
|
||||
gl::DepthMask(bool_to_gl_bool(self.depth_write));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_color_write(&mut self, color_write: (bool, bool, bool, bool)) {
|
||||
unsafe {
|
||||
if self.color_write != color_write {
|
||||
self.color_write = color_write;
|
||||
|
||||
gl::ColorMask(bool_to_gl_bool(self.color_write.0),
|
||||
bool_to_gl_bool(self.color_write.1),
|
||||
bool_to_gl_bool(self.color_write.2),
|
||||
bool_to_gl_bool(self.color_write.3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_stencil_test(&mut self, stencil_test: bool) {
|
||||
unsafe {
|
||||
if self.stencil_test != stencil_test {
|
||||
self.stencil_test = stencil_test;
|
||||
|
||||
if self.stencil_test {
|
||||
gl::Enable(gl::STENCIL_TEST);
|
||||
} else {
|
||||
gl::Disable(gl::STENCIL_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_cull_face(&mut self, cull_face: CullFace) {
|
||||
unsafe {
|
||||
if self.cull_face != cull_face {
|
||||
self.cull_face = cull_face;
|
||||
|
||||
gl::CullFace(self.cull_face.into_gl_value())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_culling(&mut self, culling: bool) {
|
||||
unsafe {
|
||||
if self.culling != culling {
|
||||
self.culling = culling;
|
||||
|
||||
if self.culling {
|
||||
gl::Enable(gl::CULL_FACE);
|
||||
} else {
|
||||
gl::Disable(gl::CULL_FACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_stencil_mask(&mut self, stencil_mask: u32) {
|
||||
unsafe {
|
||||
if self.stencil_mask != stencil_mask {
|
||||
self.stencil_mask = stencil_mask;
|
||||
|
||||
gl::StencilMask(stencil_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_clear_color(&mut self, color: Color) {
|
||||
unsafe {
|
||||
if self.clear_color != color {
|
||||
self.clear_color = color;
|
||||
|
||||
let rgba = color.as_frgba();
|
||||
gl::ClearColor(rgba.x, rgba.y, rgba.z, rgba.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_clear_depth(&mut self, depth: f32) {
|
||||
unsafe {
|
||||
if self.clear_depth != depth {
|
||||
self.clear_depth = depth;
|
||||
|
||||
gl::ClearDepth(depth as f64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_clear_stencil(&mut self, stencil: i32) {
|
||||
unsafe {
|
||||
if self.clear_stencil != stencil {
|
||||
self.clear_stencil = stencil;
|
||||
|
||||
gl::ClearStencil(stencil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_blend_func(&mut self, sfactor: GLenum, dfactor: GLenum) {
|
||||
if self.blend_src_factor != sfactor || self.blend_dst_factor != dfactor {
|
||||
self.blend_src_factor = sfactor;
|
||||
self.blend_dst_factor = dfactor;
|
||||
|
||||
unsafe {
|
||||
gl::BlendFunc(self.blend_src_factor, self.blend_dst_factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_draw_parameters(&mut self, draw_params: &DrawParameters) {
|
||||
self.set_blend(draw_params.blend);
|
||||
self.set_depth_test(draw_params.depth_test);
|
||||
self.set_depth_write(draw_params.depth_write);
|
||||
self.set_color_write(draw_params.color_write);
|
||||
self.set_stencil_test(draw_params.stencil_test);
|
||||
self.set_cull_face(draw_params.cull_face);
|
||||
self.set_culling(draw_params.culling);
|
||||
}
|
||||
}
|
||||
+50
-47
@@ -8,29 +8,36 @@ use std::{
|
||||
};
|
||||
use crate::{
|
||||
renderer::{
|
||||
framebuffer::{
|
||||
BackBuffer,
|
||||
FrameBufferTrait,
|
||||
DrawParameters,
|
||||
CullFace,
|
||||
},
|
||||
state::State,
|
||||
gpu_program::{
|
||||
UniformValue,
|
||||
GpuProgram,
|
||||
UniformLocation,
|
||||
},
|
||||
RenderPassStatistics,
|
||||
gl,
|
||||
error::RendererError,
|
||||
geometry_buffer::{
|
||||
GeometryBuffer,
|
||||
AttributeDefinition,
|
||||
AttributeKind,
|
||||
GeometryBufferKind,
|
||||
framework::{
|
||||
gl,
|
||||
geometry_buffer::{
|
||||
ElementKind,
|
||||
GeometryBuffer,
|
||||
AttributeDefinition,
|
||||
AttributeKind,
|
||||
GeometryBufferKind
|
||||
},
|
||||
gpu_texture::GpuTexture,
|
||||
gpu_program::{
|
||||
UniformValue,
|
||||
GpuProgram,
|
||||
UniformLocation,
|
||||
},
|
||||
state::{
|
||||
State,
|
||||
ColorMask,
|
||||
StencilFunc,
|
||||
StencilOp
|
||||
},
|
||||
framebuffer::{
|
||||
BackBuffer,
|
||||
FrameBufferTrait,
|
||||
DrawParameters,
|
||||
CullFace,
|
||||
}
|
||||
},
|
||||
gpu_texture::GpuTexture,
|
||||
geometry_buffer::ElementKind,
|
||||
error::RendererError,
|
||||
TextureCache,
|
||||
},
|
||||
gui::{
|
||||
@@ -80,19 +87,19 @@ impl UiShader {
|
||||
let vertex_source = include_str!("shaders/ui_vs.glsl");
|
||||
let mut program = GpuProgram::from_source("UIShader", vertex_source, fragment_source)?;
|
||||
Ok(Self {
|
||||
wvp_matrix: program.get_uniform_location("worldViewProjection")?,
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture")?,
|
||||
is_font: program.get_uniform_location("isFont")?,
|
||||
solid_color: program.get_uniform_location("solidColor")?,
|
||||
brush_type: program.get_uniform_location("brushType")?,
|
||||
gradient_point_count: program.get_uniform_location("gradientPointCount")?,
|
||||
gradient_colors: program.get_uniform_location("gradientColors")?,
|
||||
gradient_stops: program.get_uniform_location("gradientStops")?,
|
||||
gradient_origin: program.get_uniform_location("gradientOrigin")?,
|
||||
gradient_end: program.get_uniform_location("gradientEnd")?,
|
||||
bounds_min: program.get_uniform_location("boundsMin")?,
|
||||
bounds_max: program.get_uniform_location("boundsMax")?,
|
||||
resolution: program.get_uniform_location("resolution")?,
|
||||
wvp_matrix: program.uniform_location("worldViewProjection")?,
|
||||
diffuse_texture: program.uniform_location("diffuseTexture")?,
|
||||
is_font: program.uniform_location("isFont")?,
|
||||
solid_color: program.uniform_location("solidColor")?,
|
||||
brush_type: program.uniform_location("brushType")?,
|
||||
gradient_point_count: program.uniform_location("gradientPointCount")?,
|
||||
gradient_colors: program.uniform_location("gradientColors")?,
|
||||
gradient_stops: program.uniform_location("gradientStops")?,
|
||||
gradient_origin: program.uniform_location("gradientOrigin")?,
|
||||
gradient_end: program.uniform_location("gradientEnd")?,
|
||||
bounds_min: program.uniform_location("boundsMin")?,
|
||||
bounds_max: program.uniform_location("boundsMax")?,
|
||||
resolution: program.uniform_location("resolution")?,
|
||||
program,
|
||||
})
|
||||
}
|
||||
@@ -153,20 +160,16 @@ impl UiRenderer {
|
||||
if cmd.get_nesting() == 1 {
|
||||
backbuffer.clear(state, viewport, None, None, Some(0));
|
||||
}
|
||||
unsafe {
|
||||
gl::StencilOp(gl::KEEP, gl::KEEP, gl::INCR);
|
||||
// Make sure that clipping rect will be drawn at previous nesting level only (clip to parent)
|
||||
gl::StencilFunc(gl::EQUAL, i32::from(cmd.get_nesting() - 1), 0xFF);
|
||||
}
|
||||
// Draw clipping geometry to stencil buffer
|
||||
state.set_stencil_op(StencilOp{ zpass: gl::INCR, .. Default::default() });
|
||||
// Make sure that clipping rect will be drawn at previous nesting level only (clip to parent)
|
||||
state.set_stencil_func(StencilFunc { func: gl::EQUAL, ref_value: i32::from(cmd.get_nesting() - 1), ..Default::default() });
|
||||
// Draw clipping geometry to stencil buffers
|
||||
state.set_stencil_mask(0xFF);
|
||||
color_write = false;
|
||||
}
|
||||
CommandKind::Geometry => {
|
||||
unsafe {
|
||||
// Make sure to draw geometry only on clipping geometry with current nesting level
|
||||
gl::StencilFunc(gl::EQUAL, i32::from(cmd.get_nesting()), 0xFF);
|
||||
}
|
||||
// Make sure to draw geometry only on clipping geometry with current nesting level
|
||||
state.set_stencil_func(StencilFunc { func: gl::EQUAL, ref_value: i32::from(cmd.get_nesting()), ..Default::default() });
|
||||
|
||||
match cmd.texture() {
|
||||
CommandTexture::Font(font_arc) => {
|
||||
@@ -180,14 +183,14 @@ impl UiRenderer {
|
||||
);
|
||||
font.texture = Some(Arc::new(Mutex::new(tex)));
|
||||
}
|
||||
if let Some(texture) = texture_cache.get(font.texture.clone().unwrap().downcast::<Mutex<Texture>>().unwrap()) {
|
||||
if let Some(texture) = texture_cache.get(state, font.texture.clone().unwrap().downcast::<Mutex<Texture>>().unwrap()) {
|
||||
diffuse_texture = texture;
|
||||
}
|
||||
is_font_texture = true;
|
||||
}
|
||||
CommandTexture::Texture(texture) => {
|
||||
if let Ok(texture) = texture.clone().downcast::<Mutex<Texture>>() {
|
||||
if let Some(texture) = texture_cache.get(texture) {
|
||||
if let Some(texture) = texture_cache.get(state, texture) {
|
||||
diffuse_texture = texture;
|
||||
}
|
||||
}
|
||||
@@ -270,7 +273,7 @@ impl UiRenderer {
|
||||
let params = DrawParameters {
|
||||
cull_face: CullFace::Back,
|
||||
culling: false,
|
||||
color_write: (color_write, color_write, color_write, color_write),
|
||||
color_write: ColorMask::all(color_write),
|
||||
depth_write: false,
|
||||
stencil_test: cmd.get_nesting() != 0,
|
||||
depth_test: false,
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
use std::{
|
||||
io::{Seek, Read, SeekFrom},
|
||||
io::{
|
||||
Seek,
|
||||
Read,
|
||||
SeekFrom,
|
||||
},
|
||||
collections::HashMap,
|
||||
};
|
||||
use byteorder::ReadBytesExt;
|
||||
use crate::{
|
||||
resource::{
|
||||
fbx::{FbxNode, Fbx},
|
||||
fbx::attribute::FbxAttribute,
|
||||
fbx::error::FbxError,
|
||||
resource::fbx::{
|
||||
FbxNode,
|
||||
Fbx,
|
||||
attribute::FbxAttribute,
|
||||
error::FbxError,
|
||||
},
|
||||
core::pool::{
|
||||
Pool,
|
||||
Handle,
|
||||
},
|
||||
};
|
||||
use crate::core::{
|
||||
pool::{Pool, Handle},
|
||||
};
|
||||
|
||||
pub fn read_ascii<R>(reader: &mut R, buf_len: u64) -> Result<Fbx, FbxError>
|
||||
@@ -54,8 +60,8 @@ pub fn read_ascii<R>(reader: &mut R, buf_len: u64) -> Result<Fbx, FbxError>
|
||||
// Parse string
|
||||
let mut read_value = false;
|
||||
name.clear();
|
||||
for i in 0..buffer.len() {
|
||||
let symbol = unsafe { *buffer.get_unchecked(i as usize) };
|
||||
for (i, symbol) in buffer.iter().enumerate() {
|
||||
let symbol = *symbol;
|
||||
if i == 0 && (symbol == b'-' || symbol.is_ascii_digit()) {
|
||||
read_value = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user