summaryrefslogtreecommitdiff
path: root/engine/src/renderer/opengl.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-03-20 14:22:19 +0100
committerHampusM <hampus@hampusmat.com>2026-03-20 14:22:19 +0100
commitf285f82072b491b1f3cc92db8e08485f26779d5a (patch)
treebf6c6c61cdfb3a12550e55966c8552957ade9e71 /engine/src/renderer/opengl.rs
parent0546d575c11d3668d0f95933697ae4f670fe2a55 (diff)
feat(engine): use slang for shadersHEADmaster
Diffstat (limited to 'engine/src/renderer/opengl.rs')
-rw-r--r--engine/src/renderer/opengl.rs769
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 }
+ }
+}