diff options
Diffstat (limited to 'engine/src/renderer/opengl.rs')
| -rw-r--r-- | engine/src/renderer/opengl.rs | 769 |
1 files changed, 224 insertions, 545 deletions
diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs index 4bd67a4..c72a344 100644 --- a/engine/src/renderer/opengl.rs +++ b/engine/src/renderer/opengl.rs @@ -1,16 +1,14 @@ //! OpenGL renderer. use std::any::type_name; +use std::borrow::Cow; use std::collections::HashMap; -use std::ffi::CString; -use std::io::{Error as IoError, ErrorKind as IoErrorKind}; -use std::path::Path; use ecs::actions::Actions; use ecs::entity::obtainer::Obtainer as EntityObtainer; use ecs::event::component::{Changed, Removed}; use ecs::pair::{ChildOf, Pair, Wildcard}; -use ecs::phase::Phase; +use ecs::phase::{Phase, START as START_PHASE}; use ecs::query::term::Without; use ecs::sole::Single; use ecs::system::observer::Observe; @@ -44,6 +42,7 @@ use opengl_bindings::shader::{ Kind as ShaderKind, Program as GlShaderProgram, Shader as GlShader, + // UniformLocation as GlUniformLocation, }; use opengl_bindings::texture::{ Filtering as GlTextureFiltering, @@ -59,21 +58,13 @@ use opengl_bindings::vertex_array::{ }; use opengl_bindings::{ContextWithFns, CurrentContextWithFns}; use safer_ffi::layout::ReprC; +use zerocopy::{Immutable, IntoBytes}; use crate::asset::{Assets, Id as AssetId}; -use crate::camera::Camera; -use crate::color::Color; use crate::data_types::dimens::Dimens; use crate::image::{ColorType as ImageColorType, Image}; -use crate::lighting::{DirectionalLight, GlobalLight, PointLight}; -use crate::material::{Flags as MaterialFlags, Material}; use crate::matrix::Matrix; use crate::model::Model; -use crate::opengl::glsl::{ - PreprocessingError as GlslPreprocessingError, - preprocess as glsl_preprocess, -}; -use crate::projection::{ClipVolume, Projection}; use crate::renderer::object::{ Id as RendererObjectId, Kind as RendererObjectKind, @@ -91,17 +82,23 @@ use crate::renderer::{ CommandQueue as RendererCommandQueue, CtxUsedByWindow as RendererCtxUsedByWindow, GraphicsProperties, + PRE_RENDER_PHASE, RENDER_PHASE, SurfaceId, SurfaceSpec, WindowUsingRendererCtx, }; +use crate::shader::cursor::BindingValue as ShaderBindingValue; +use crate::shader::{ + Error as ShaderError, + Program as ShaderProgram, + Stage as ShaderStage, +}; use crate::texture::{ Filtering as TextureFiltering, Properties as TextureProperties, Wrapping as TextureWrapping, }; -use crate::transform::WorldPosition; use crate::vector::{Vec2, Vec3}; use crate::windowing::Context as WindowingContext; use crate::windowing::window::{ @@ -115,12 +112,6 @@ mod glutin_compat; mod graphics_mesh; mod vertex; -const AMBIENT_MAP_TEXTURE_UNIT: u32 = 0; -const DIFFUSE_MAP_TEXTURE_UNIT: u32 = 1; -const SPECULAR_MAP_TEXTURE_UNIT: u32 = 2; - -const DEFAULT_TEXTURE_OBJECT_ID: RendererObjectId = RendererObjectId::Other(0xaa); - declare_entity!( pub POST_RENDER_PHASE, (Phase, Pair::builder().relation::<ChildOf>().target_id(*RENDER_PHASE).build()) @@ -136,9 +127,9 @@ struct WindowGlConfig struct GraphicsContext { gl_context: ContextWithFns, - shader_program: Option<GlShaderProgram>, graphics_mesh_store: GraphicsMeshStore, surfaces: HashMap<SurfaceId, GlutinSurface<GlutinWindowSurface>>, + uniform_buffer_objs: HashMap<u32, opengl_bindings::buffer::Buffer<u8>>, } #[derive(Debug, Default)] @@ -155,9 +146,12 @@ impl ecs::extension::Extension for Extension { fn collect(self, mut collector: ecs::extension::Collector<'_>) { + collector.add_declared_entity(&PRE_RENDER_PHASE); collector.add_declared_entity(&RENDER_PHASE); collector.add_declared_entity(&POST_RENDER_PHASE); + collector.add_system(*START_PHASE, super::init); + collector.add_system(*RENDER_PHASE, super::enqueue_commands); collector.add_system(*RENDER_PHASE, handle_commands); @@ -617,9 +611,9 @@ fn init_window_graphics( let renderer_ctx_ent_id = actions.spawn(( GraphicsContext { gl_context, - shader_program: None, graphics_mesh_store: GraphicsMeshStore::default(), surfaces: HashMap::from([(surface_id, surface)]), + uniform_buffer_objs: HashMap::new(), }, RendererObjectStore::default(), RendererCommandQueue::default(), @@ -657,17 +651,17 @@ fn handle_commands( { let GraphicsContext { ref gl_context, - ref mut shader_program, ref mut graphics_mesh_store, ref surfaces, + ref mut uniform_buffer_objs, } = *graphics_ctx; let mut opt_curr_gl_ctx: Option<CurrentContextWithFns> = None; - let mut opt_curr_camera: Option<(Camera, WorldPosition)> = None; + let mut activated_gl_shader_program: Option<GlShaderProgram> = None; for command in command_queue.drain() { - let tracing_span = tracing::info_span!("handle_cmd", command = ?command); + let tracing_span = tracing::info_span!("handle_cmd"); let _tracing_span_enter = tracing_span.enter(); match command { @@ -724,89 +718,148 @@ fn handle_commands( tracing::error!("Failed to swap buffers: {err}"); } } - RendererCommand::UseShader => { + RendererCommand::CreateShaderProgram( + shader_program_obj_id, + shader_program, + ) => { let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { tracing::error!("No GL context is current"); continue; }; - let _shader_program = shader_program.get_or_insert_with(|| { - create_default_shader_program(&curr_gl_ctx).unwrap() - }); - } - RendererCommand::ActivateShader => { - let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { - tracing::error!("No GL context is current"); + if renderer_object_store.contains_with_id(&shader_program_obj_id) { + tracing::error!( + object_id=?shader_program_obj_id, + "Object store already contains a object with this ID" + ); continue; - }; + } - let Some(shader_program) = shader_program else { - tracing::error!("Shader does not exist"); - continue; - }; + let gl_shader_program = + match create_shader_program(&curr_gl_ctx, &shader_program) { + Ok(gl_shader_program) => gl_shader_program, + Err(err) => { + tracing::error!("Failed to create shader program: {err}"); + continue; + } + }; - shader_program.activate(&curr_gl_ctx); - } - RendererCommand::UseCamera(camera, camera_world_pos) => { - opt_curr_camera = Some((camera, camera_world_pos)); + renderer_object_store.insert( + shader_program_obj_id, + RendererObject::from_raw( + gl_shader_program.into_raw(), + RendererObjectKind::ShaderProgram, + ), + ); } - RendererCommand::ApplyTransform { transform, window_size } => { + RendererCommand::ActivateShader(shader_program_obj_id) => { let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { tracing::error!("No GL context is current"); continue; }; - let Some(shader_program) = shader_program else { - tracing::error!("Shader does not exist"); + let Some(shader_program_obj) = renderer_object_store + .get_shader_program_obj(&shader_program_obj_id) + else { + tracing::error!( + "Shader object does not exist or has a wrong kind" + ); continue; }; - let Some((camera, camera_world_pos)) = &opt_curr_camera else { - tracing::error!("No current camera"); - continue; - }; + let gl_shader_program = + GlShaderProgram::from_raw(shader_program_obj.as_raw()); - apply_transformation_matrices( - &curr_gl_ctx, - Transformation { - position: transform.position, - scale: transform.scale, - }, - shader_program, - &camera, - &camera_world_pos, - &window_size, - ); + gl_shader_program.activate(&curr_gl_ctx); + + activated_gl_shader_program = Some(gl_shader_program); } - RendererCommand::SetShaderDirectionalLights(directional_lights) => { + RendererCommand::SetShaderBinding(binding_location, binding_value) => { let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { tracing::error!("No GL context is current"); continue; }; - let Some(shader_program) = shader_program else { - tracing::error!("Shader does not exist"); + if activated_gl_shader_program.is_none() { + tracing::error!("No shader program is activated"); continue; - }; + } - set_shader_directional_lights( - curr_gl_ctx, - shader_program, - &directional_lights, - ); - } - RendererCommand::SetShaderPointLights(point_lights) => { - let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { - tracing::error!("No GL context is current"); - continue; - }; + if let ShaderBindingValue::Texture(texture_asset) = &binding_value { + let Some(texture_obj) = renderer_object_store.get_texture_obj( + &RendererObjectId::Asset(texture_asset.id()), + ) else { + tracing::error!( + "Texture {:?} does not exist in renderer object store", + assets.get_label(texture_asset) + ); + continue; + }; + + let gl_texture = GlTexture::from_raw(texture_obj.as_raw()); + + gl_texture.bind_to_texture_unit( + curr_gl_ctx, + binding_location.binding_index, + ); + + // gl_shader_program.set_uniform_at_location( + // curr_gl_ctx, + // GlUniformLocation::from_number( + // binding_location.binding_index as i32, + // ), + // &binding_location.binding_index, + // ); - let Some(shader_program) = shader_program else { - tracing::error!("Shader does not exist"); continue; - }; + } - set_shader_point_lights(curr_gl_ctx, shader_program, &point_lights); + let binding_index = binding_location.binding_index; + + let uniform_buffer = + uniform_buffer_objs.entry(binding_index).or_insert_with(|| { + let uniform_buf = + opengl_bindings::buffer::Buffer::<u8>::new(curr_gl_ctx); + + uniform_buf + .init( + curr_gl_ctx, + binding_location.binding_size, + opengl_bindings::buffer::Usage::Dynamic, + ) + .unwrap(); + + uniform_buf.bind_to_indexed_target( + curr_gl_ctx, + opengl_bindings::buffer::BindingTarget::UniformBuffer, + binding_index as u32, + ); + + uniform_buf + }); + + let fvec3_value; + + uniform_buffer + .store_at_byte_offset( + curr_gl_ctx, + binding_location.byte_offset, + match binding_value { + ShaderBindingValue::Uint(ref value) => value.as_bytes(), + ShaderBindingValue::Int(ref value) => value.as_bytes(), + ShaderBindingValue::Float(ref value) => value.as_bytes(), + ShaderBindingValue::FVec3(value) => { + fvec3_value = CF32Vec3::from(value); + + fvec3_value.as_bytes() + } + ShaderBindingValue::FMat4x4(ref value) => { + value.items().as_bytes() + } + ShaderBindingValue::Texture(_) => unreachable!(), + }, + ) + .unwrap(); } RendererCommand::CreateTexture(texture) => { let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { @@ -815,6 +868,7 @@ fn handle_commands( }; let Some(texture_image) = assets.get(&texture.asset_handle) else { + tracing::error!("Texture asset is not loaded",); continue; }; @@ -828,58 +882,14 @@ fn handle_commands( tracing::error!("Failed to create texture object: {err}"); } } - RendererCommand::UseMaterial { - material_asset, - material_flags, - global_light, - } => { - let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { - tracing::error!("No GL context is current"); - continue; - }; - - let Some(shader_program) = shader_program else { - tracing::error!("Shader does not exist"); - continue; - }; - - let Some((_, camera_world_pos)) = &opt_curr_camera else { - tracing::error!("No current camera"); - continue; - }; - - let material = match material_asset.as_ref() { - Some(material_asset) => { - let Some(material) = assets.get(&material_asset) else { - continue; - }; - - material - } - None => &Material::default(), - }; - - set_shader_material( - curr_gl_ctx, - material, - &material_flags, - &global_light, - shader_program, - camera_world_pos, - ); - - bind_material_textures( - curr_gl_ctx, - material, - &mut renderer_object_store, - ); - } RendererCommand::DrawMesh { mesh_asset } => { let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { tracing::error!("No GL context is current"); continue; }; + // tracing::warn!("ARGH! Drawing mesh"); + let graphics_mesh = match graphics_mesh_store.graphics_meshes.get(&mesh_asset.id()) { Some(graphics_mesh) => graphics_mesh, @@ -930,21 +940,6 @@ fn handle_commands( } } -fn create_default_texture(current_context: &CurrentContextWithFns<'_>) -> GlTexture -{ - match create_gl_texture( - current_context, - &Image::from_color(Dimens { width: 1, height: 1 }, Color::WHITE_U8), - &TextureProperties::default(), - ) { - Ok(gl_texture) => gl_texture, - Err( - GlTextureGenerateError::SizeWidthValueTooLarge { value: _, max_value: _ } - | GlTextureGenerateError::SizeHeightValueTooLarge { value: _, max_value: _ }, - ) => unreachable!(), - } -} - #[tracing::instrument(skip_all)] fn create_texture_object( curr_gl_ctx: &CurrentContextWithFns<'_>, @@ -975,53 +970,6 @@ fn create_texture_object( Ok(()) } -fn bind_material_textures( - current_context: &CurrentContextWithFns<'_>, - material: &Material, - renderer_object_store: &mut RendererObjectStore, -) -{ - let material_texture_maps = [ - (&material.ambient_map, AMBIENT_MAP_TEXTURE_UNIT), - (&material.diffuse_map, DIFFUSE_MAP_TEXTURE_UNIT), - (&material.specular_map, SPECULAR_MAP_TEXTURE_UNIT), - ]; - - for (texture, texture_unit) in material_texture_maps { - let Some(texture) = texture else { - let default_texture_obj = renderer_object_store - .entry(DEFAULT_TEXTURE_OBJECT_ID) - .or_insert_with(|| { - RendererObject::from_raw( - create_default_texture(current_context).into_raw(), - RendererObjectKind::Texture, - ) - }); - - let gl_texture = GlTexture::from_raw(default_texture_obj.as_raw()); - - gl_texture.bind_to_texture_unit(current_context, texture_unit); - - continue; - }; - - let texture_object_id = RendererObjectId::Asset(texture.asset_handle.id()); - - let Some(texture_obj) = renderer_object_store.get_texture_obj(&texture_object_id) - else { - tracing::error!( - texture_object_id=?texture_object_id, - "Texture object does not exist" - ); - continue; - }; - - let gl_texture = GlTexture::from_raw(texture_obj.as_raw()); - - gl_texture.bind_to_texture_unit(current_context, texture_unit); - } -} - fn set_viewport( current_context: &CurrentContextWithFns<'_>, position: Vec2<u32>, @@ -1104,21 +1052,60 @@ fn create_gl_texture( Ok(gl_texture) } -const VERTEX_GLSL_SHADER_SRC: &str = include_str!("opengl/glsl/vertex.glsl"); -const FRAGMENT_GLSL_SHADER_SRC: &str = include_str!("opengl/glsl/fragment.glsl"); - -const VERTEX_DATA_GLSL_SHADER_SRC: &str = include_str!("opengl/glsl/vertex_data.glsl"); -const LIGHT_GLSL_SHADER_SRC: &str = include_str!("opengl/glsl/light.glsl"); - -fn create_default_shader_program( +fn create_shader_program( current_context: &CurrentContextWithFns<'_>, + shader_program: &ShaderProgram, ) -> Result<GlShaderProgram, CreateShaderError> { + let shader_program_reflection = shader_program.reflection(0).expect("Not possible"); + + let (vs_entry_point_index, vs_entry_point_reflection) = shader_program_reflection + .entry_points() + .enumerate() + .find(|(_, entry_point)| entry_point.stage() == ShaderStage::Vertex) + .ok_or_else(|| { + CreateShaderError::NoShaderStageEntrypointFound(ShaderStage::Vertex) + })?; + + let vertex_shader_entry_point_code = shader_program + .get_entry_point_code(vs_entry_point_index.try_into().expect( + "Vertex shader entry point index does not fit in 32-bit unsigned int", + )) + .map_err(|err| CreateShaderError::GetShaderEntryPointCodeFailed { + err, + stage: ShaderStage::Vertex, + entrypoint: vs_entry_point_reflection + .name() + .map(|name| name.to_string().into()) + .unwrap_or("(none)".into()), + })?; + + let (fs_entry_point_index, fs_entry_point_reflection) = shader_program_reflection + .entry_points() + .enumerate() + .find(|(_, entry_point)| entry_point.stage() == ShaderStage::Fragment) + .ok_or_else(|| { + CreateShaderError::NoShaderStageEntrypointFound(ShaderStage::Fragment) + })?; + + let fragment_shader_entry_point_code = shader_program + .get_entry_point_code(fs_entry_point_index.try_into().expect( + "Fragment shader entry point index does not fit in 32-bit unsigned int", + )) + .map_err(|err| CreateShaderError::GetShaderEntryPointCodeFailed { + err, + stage: ShaderStage::Fragment, + entrypoint: fs_entry_point_reflection + .name() + .map(|name| name.to_string().into()) + .unwrap_or("(none)".into()), + })?; + let vertex_shader = GlShader::new(current_context, ShaderKind::Vertex); vertex_shader.set_source( current_context, - &*glsl_preprocess(VERTEX_GLSL_SHADER_SRC, &get_glsl_shader_content)?, + &vertex_shader_entry_point_code.as_str().unwrap(), )?; vertex_shader.compile(current_context)?; @@ -1127,7 +1114,7 @@ fn create_default_shader_program( fragment_shader.set_source( current_context, - &*glsl_preprocess(FRAGMENT_GLSL_SHADER_SRC, &get_glsl_shader_content)?, + &fragment_shader_entry_point_code.as_str().unwrap(), )?; fragment_shader.compile(current_context)?; @@ -1145,340 +1132,22 @@ fn create_default_shader_program( #[derive(Debug, thiserror::Error)] enum CreateShaderError { - #[error(transparent)] - ShaderError(#[from] GlShaderError), - - #[error(transparent)] - PreprocessingError(#[from] GlslPreprocessingError), -} - -fn get_glsl_shader_content(path: &Path) -> Result<Vec<u8>, std::io::Error> -{ - if path == Path::new("vertex_data.glsl") { - return Ok(VERTEX_DATA_GLSL_SHADER_SRC.as_bytes().to_vec()); - } - - if path == Path::new("light.glsl") { - return Ok(LIGHT_GLSL_SHADER_SRC.as_bytes().to_vec()); - } - - Err(IoError::new( - IoErrorKind::NotFound, - format!("Content for shader file {} not found", path.display()), - )) -} - -fn apply_transformation_matrices( - current_context: &CurrentContextWithFns<'_>, - transformation: Transformation, - gl_shader_program: &mut GlShaderProgram, - camera: &Camera, - camera_world_pos: &WorldPosition, - window_size: &Dimens<u32>, -) -{ - gl_shader_program.set_uniform( - current_context, - c"model", - &opengl_bindings::data_types::Matrix { - items: create_transformation_matrix(transformation).items, - }, - ); - - let view_matrix = create_view_matrix(camera, &camera_world_pos.position); - - gl_shader_program.set_uniform( - current_context, - c"view", - &opengl_bindings::data_types::Matrix { items: view_matrix.items }, - ); - - #[allow(clippy::cast_precision_loss)] - let proj_matrix = match &camera.projection { - Projection::Perspective(perspective_proj) => perspective_proj.to_matrix_rh( - window_size.width as f32 / window_size.height as f32, - ClipVolume::NegOneToOne, - ), - Projection::Orthographic(orthographic_proj) => orthographic_proj - .to_matrix_rh(&camera_world_pos.position, ClipVolume::NegOneToOne), - }; - - gl_shader_program.set_uniform( - current_context, - c"projection", - &opengl_bindings::data_types::Matrix { items: proj_matrix.items }, - ); -} - -fn set_shader_directional_lights( - curr_gl_ctx: &CurrentContextWithFns<'_>, - gl_shader_program: &mut GlShaderProgram, - directional_lights: &[DirectionalLight], -) -{ - debug_assert!( - directional_lights.len() < 64, - "Shader cannot handle more than 64 directional lights" - ); - - for (dir_light_index, dir_light) in directional_lights.iter().enumerate() { - let direction: opengl_bindings::data_types::Vec3<_> = dir_light.direction.into(); - - gl_shader_program.set_uniform( - curr_gl_ctx, - &create_light_uniform_name( - "directional_lights", - dir_light_index, - "direction", - ), - &direction, - ); - - set_light_phong_uniforms( - curr_gl_ctx, - gl_shader_program, - "directional_lights", - dir_light_index, - dir_light, - ); - } - - // There probably won't be more than 2147483648 directional lights - #[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)] - gl_shader_program.set_uniform( - curr_gl_ctx, - c"directional_light_cnt", - &(directional_lights.len() as i32), - ); -} - -fn set_shader_point_lights( - curr_gl_ctx: &CurrentContextWithFns<'_>, - gl_shader_program: &mut GlShaderProgram, - point_lights: &[(PointLight, WorldPosition)], -) -{ - debug_assert!( - point_lights.len() < 64, - "Shader cannot handle more than 64 point lights" - ); - - for (point_light_index, (point_light, point_light_world_pos)) in - point_lights.iter().enumerate() - { - let pos: opengl_bindings::data_types::Vec3<_> = - (point_light_world_pos.position + point_light.local_position).into(); - - gl_shader_program.set_uniform( - curr_gl_ctx, - &create_light_uniform_name("point_lights", point_light_index, "position"), - &pos, - ); - - set_light_phong_uniforms( - curr_gl_ctx, - gl_shader_program, - "point_lights", - point_light_index, - &*point_light, - ); - - set_light_attenuation_uniforms( - curr_gl_ctx, - gl_shader_program, - "point_lights", - point_light_index, - &*point_light, - ); - } - - // There probably won't be more than 2147483648 point lights - #[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)] - gl_shader_program.set_uniform( - curr_gl_ctx, - c"point_light_cnt", - &(point_lights.len() as i32), - ); -} - -fn set_shader_material( - curr_gl_ctx: &CurrentContextWithFns<'_>, - material: &Material, - material_flags: &MaterialFlags, - global_light: &GlobalLight, - gl_shader_program: &mut GlShaderProgram, - camera_world_pos: &WorldPosition, -) -{ - let ambient: opengl_bindings::data_types::Vec3<_> = - Vec3::from(if material_flags.use_ambient_color { - material.ambient.clone() - } else { - global_light.ambient.clone() - }) - .into(); - - gl_shader_program.set_uniform(curr_gl_ctx, c"material.ambient", &ambient); - - let diffuse: opengl_bindings::data_types::Vec3<_> = - Vec3::from(material.diffuse.clone()).into(); - - gl_shader_program.set_uniform(curr_gl_ctx, c"material.diffuse", &diffuse); - - let specular: opengl_bindings::data_types::Vec3<_> = - Vec3::from(material.specular.clone()).into(); - - #[allow(clippy::cast_possible_wrap)] - gl_shader_program.set_uniform(curr_gl_ctx, c"material.specular", &specular); - - #[allow(clippy::cast_possible_wrap)] - gl_shader_program.set_uniform( - curr_gl_ctx, - c"material.ambient_map", - &(AMBIENT_MAP_TEXTURE_UNIT as i32), - ); - - #[allow(clippy::cast_possible_wrap)] - gl_shader_program.set_uniform( - curr_gl_ctx, - c"material.diffuse_map", - &(DIFFUSE_MAP_TEXTURE_UNIT as i32), - ); - - #[allow(clippy::cast_possible_wrap)] - gl_shader_program.set_uniform( - curr_gl_ctx, - c"material.specular_map", - &(SPECULAR_MAP_TEXTURE_UNIT as i32), - ); - - gl_shader_program.set_uniform( - curr_gl_ctx, - c"material.shininess", - &material.shininess, - ); - - let view_pos: opengl_bindings::data_types::Vec3<_> = camera_world_pos.position.into(); - - gl_shader_program.set_uniform(curr_gl_ctx, c"view_pos", &view_pos); -} - -fn set_light_attenuation_uniforms( - current_context: &CurrentContextWithFns<'_>, - gl_shader_program: &mut GlShaderProgram, - light_array: &str, - light_index: usize, - light: &PointLight, -) -{ - gl_shader_program.set_uniform( - current_context, - &create_light_uniform_name( - light_array, - light_index, - "attenuation_props.constant", - ), - &light.attenuation_params.constant, - ); - - gl_shader_program.set_uniform( - current_context, - &create_light_uniform_name(light_array, light_index, "attenuation_props.linear"), - &light.attenuation_params.linear, - ); - - gl_shader_program.set_uniform( - current_context, - &create_light_uniform_name( - light_array, - light_index, - "attenuation_props.quadratic", - ), - &light.attenuation_params.quadratic, - ); -} - -fn set_light_phong_uniforms( - current_context: &CurrentContextWithFns<'_>, - gl_shader_program: &mut GlShaderProgram, - light_array: &str, - light_index: usize, - light: &impl Light, -) -{ - gl_shader_program.set_uniform( - current_context, - &create_light_uniform_name(light_array, light_index, "phong.diffuse"), - &opengl_bindings::data_types::Vec3 { - x: light.diffuse().red, - y: light.diffuse().green, - z: light.diffuse().blue, - }, - ); - - gl_shader_program.set_uniform( - current_context, - &create_light_uniform_name(light_array, light_index, "phong.specular"), - &opengl_bindings::data_types::Vec3 { - x: light.specular().red, - y: light.specular().green, - z: light.specular().blue, - }, - ); -} - -trait Light -{ - fn diffuse(&self) -> &Color<f32>; - fn specular(&self) -> &Color<f32>; -} - -impl Light for PointLight -{ - fn diffuse(&self) -> &Color<f32> - { - &self.diffuse - } - - fn specular(&self) -> &Color<f32> - { - &self.specular - } -} - -impl Light for DirectionalLight -{ - fn diffuse(&self) -> &Color<f32> - { - &self.diffuse - } - - fn specular(&self) -> &Color<f32> + #[error( + "Failed to get code of shader program entry point {entrypoint} of stage {stage:?}" + )] + GetShaderEntryPointCodeFailed { - &self.specular - } -} - -fn create_light_uniform_name( - light_array: &str, - light_index: usize, - light_field: &str, -) -> CString -{ - unsafe { - CString::from_vec_with_nul_unchecked( - format!("{light_array}[{light_index}].{light_field}\0").into(), - ) - } -} - -fn create_view_matrix(camera: &Camera, camera_pos: &Vec3<f32>) -> Matrix<f32, 4, 4> -{ - let mut view = Matrix::new(); + #[source] + err: ShaderError, + stage: ShaderStage, + entrypoint: Cow<'static, str>, + }, - view.look_at(&camera_pos, &camera.target, &camera.global_up); + #[error("No entrypoint was found for shader stage {0:?}")] + NoShaderStageEntrypointFound(ShaderStage), - view + #[error(transparent)] + ShaderError(#[from] GlShaderError), } #[tracing::instrument(skip_all)] @@ -1524,23 +1193,6 @@ fn opengl_debug_message_cb( }; } -#[derive(Debug)] -struct Transformation -{ - position: Vec3<f32>, - scale: Vec3<f32>, -} - -fn create_transformation_matrix(transformation: Transformation) -> Matrix<f32, 4, 4> -{ - let mut matrix = Matrix::new_identity(); - - matrix.translate(&transformation.position); - matrix.scale(&transformation.scale); - - matrix -} - #[inline] fn texture_wrapping_to_gl(texture_wrapping: TextureWrapping) -> GlTextureWrapping { @@ -1569,7 +1221,8 @@ impl<Value: ReprC + Copy> From<Vec2<Value>> for opengl_bindings::data_types::Vec } } -impl<Value: ReprC + Copy> From<Vec3<Value>> for opengl_bindings::data_types::Vec3<Value> +impl<Value: ReprC + IntoBytes + Copy> From<Vec3<Value>> + for opengl_bindings::data_types::Vec3<Value> { fn from(vec3: Vec3<Value>) -> Self { @@ -1577,6 +1230,15 @@ impl<Value: ReprC + Copy> From<Vec3<Value>> for opengl_bindings::data_types::Vec } } +impl<Value: ReprC + Copy> From<Matrix<Value, 4, 4>> + for opengl_bindings::data_types::Matrix<Value, 4, 4> +{ + fn from(matrix: Matrix<Value, 4, 4>) -> Self + { + Self { items: matrix.items } + } +} + impl<Value: Copy> From<Dimens<Value>> for opengl_bindings::data_types::Dimens<Value> { fn from(dimens: Dimens<Value>) -> Self @@ -1611,3 +1273,20 @@ impl From<crate::draw_flags::PolygonModeFace> for opengl_bindings::misc::Polygon } } } + +#[derive(Debug, IntoBytes, Immutable)] +#[repr(C)] +pub struct CF32Vec3 +{ + x: f32, + y: f32, + z: f32, +} + +impl From<Vec3<f32>> for CF32Vec3 +{ + fn from(src: Vec3<f32>) -> Self + { + Self { x: src.x, y: src.y, z: src.z } + } +} |
