isolated all unsafe opengl calls into framework mod

This commit is contained in:
Dmitry
2020-03-22 13:01:41 +03:00
parent ed6cb10436
commit e5ea130c01
20 changed files with 1066 additions and 921 deletions
+2 -1
View File
@@ -2,4 +2,5 @@
**/*.rs.bk
/cloc
*.lock
.*
.*
/*.log
+12 -17
View File
@@ -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)?;
+23 -21
View File
@@ -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,
+50 -50
View File
@@ -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,
+3 -3
View File
@@ -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(&params);
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 {
+132
View File
@@ -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());
}
}
}
}
+387
View File
@@ -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
View File
@@ -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
View File
@@ -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());
}
}
}
}
+75 -65
View File
@@ -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
}
}
+104 -90
View File
@@ -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,
})
],
));
+49 -38
View File
@@ -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()))
]
],
));
}
-246
View File
@@ -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
View File
@@ -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,
+16 -10
View File
@@ -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;
}