summaryrefslogtreecommitdiff
path: root/engine/src/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/renderer')
-rw-r--r--engine/src/renderer/opengl.rs427
-rw-r--r--engine/src/renderer/opengl/glsl/light.glsl4
-rw-r--r--engine/src/renderer/opengl/vertex.rs64
3 files changed, 327 insertions, 168 deletions
diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs
index deb26a8..cfd046f 100644
--- a/engine/src/renderer/opengl.rs
+++ b/engine/src/renderer/opengl.rs
@@ -3,29 +3,39 @@
use std::collections::HashMap;
use std::ffi::{c_void, CString};
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
-use std::ops::Deref;
use std::path::Path;
use std::process::abort;
use ecs::actions::Actions;
use ecs::component::local::Local;
-use ecs::query::options::{Not, With};
+use ecs::component::Handle as ComponentHandle;
+use ecs::phase::START as START_PHASE;
+use ecs::query::term::Without;
use ecs::sole::Single;
use ecs::system::{Into as _, System};
use ecs::{Component, Query};
+use crate::asset::{Assets, Id as AssetId};
use crate::camera::{Active as ActiveCamera, Camera};
use crate::color::Color;
use crate::data_types::dimens::Dimens;
use crate::draw_flags::{DrawFlags, NoDraw, PolygonModeConfig};
-use crate::event::{Present as PresentEvent, Start as StartEvent};
+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::mesh::Mesh;
+use crate::model::Model;
use crate::opengl::buffer::{Buffer, Usage as BufferUsage};
-#[cfg(feature = "debug")]
-use crate::opengl::debug::{MessageSeverity, MessageSource, MessageType};
+use crate::opengl::debug::{
+ enable_debug_output,
+ set_debug_message_callback,
+ set_debug_message_control,
+ MessageIdsAction,
+ MessageSeverity,
+ MessageSource,
+ MessageType,
+};
use crate::opengl::glsl::{
preprocess as glsl_preprocess,
PreprocessingError as GlslPreprocessingError,
@@ -37,32 +47,50 @@ use crate::opengl::shader::{
Shader as GlShader,
};
use crate::opengl::texture::{
- set_active_texture_unit,
+ Filtering as GlTextureFiltering,
+ PixelDataFormat as GlTexturePixelDataFormat,
Texture as GlTexture,
- TextureUnit,
+ Wrapping as GlTextureWrapping,
};
use crate::opengl::vertex_array::{
DataType as VertexArrayDataType,
PrimitiveKind,
VertexArray,
};
-use crate::opengl::{clear_buffers, enable, BufferClearMask, Capability};
-use crate::projection::{new_perspective_matrix, Projection};
-use crate::texture::{Id as TextureId, Texture};
-use crate::transform::{Position, Scale};
-use crate::util::NeverDrop;
+use crate::opengl::{
+ clear_buffers,
+ enable,
+ get_context_flags as get_opengl_context_flags,
+ BufferClearMask,
+ Capability,
+ ContextFlags,
+};
+use crate::projection::{ClipVolume, Projection};
+use crate::renderer::opengl::vertex::{AttributeComponentType, Vertex};
+use crate::renderer::RENDER_PHASE;
+use crate::texture::{
+ Filtering as TextureFiltering,
+ Properties as TextureProperties,
+ Wrapping as TextureWrapping,
+};
+use crate::transform::{Scale, WorldPosition};
+use crate::util::{defer, Defer, RefOrValue};
use crate::vector::{Vec2, Vec3};
-use crate::vertex::{AttributeComponentType, Vertex};
use crate::window::Window;
-type RenderableEntity = (
- Mesh,
- Material,
- Option<MaterialFlags>,
- Option<Position>,
- Option<Scale>,
- Option<DrawFlags>,
- Option<GlObjects>,
+mod vertex;
+
+const AMBIENT_MAP_TEXTURE_UNIT: u32 = 0;
+const DIFFUSE_MAP_TEXTURE_UNIT: u32 = 1;
+const SPECULAR_MAP_TEXTURE_UNIT: u32 = 2;
+
+type RenderableEntity<'a> = (
+ &'a Model,
+ Option<&'a MaterialFlags>,
+ Option<&'a WorldPosition>,
+ Option<&'a Scale>,
+ Option<&'a DrawFlags>,
+ Option<&'a GlObjects>,
);
#[derive(Debug, Default)]
@@ -73,10 +101,10 @@ impl ecs::extension::Extension for Extension
{
fn collect(self, mut collector: ecs::extension::Collector<'_>)
{
- collector.add_system(StartEvent, initialize);
+ collector.add_system(*START_PHASE, initialize);
collector.add_system(
- PresentEvent,
+ *RENDER_PHASE,
render
.into_system()
.initialize((GlobalGlObjects::default(),)),
@@ -101,8 +129,9 @@ fn initialize(window: Single<Window>)
}
});
- #[cfg(feature = "debug")]
- initialize_debug();
+ if get_opengl_context_flags().contains(ContextFlags::DEBUG) {
+ initialize_debug();
+ }
let window_size = window.size().expect("Failed to get window size");
@@ -116,34 +145,31 @@ fn initialize(window: Single<Window>)
enable(Capability::MultiSample);
}
+#[tracing::instrument(skip_all)]
#[allow(clippy::too_many_arguments)]
fn render(
- query: Query<RenderableEntity, Not<With<NoDraw>>>,
- point_light_query: Query<(PointLight,)>,
- directional_lights: Query<(DirectionalLight,)>,
- camera_query: Query<(Camera, Position, ActiveCamera)>,
+ query: Query<RenderableEntity<'_>, (Without<NoDraw>,)>,
+ point_light_query: Query<(&PointLight, &WorldPosition)>,
+ directional_lights: Query<(&DirectionalLight,)>,
+ camera_query: Query<(&Camera, &WorldPosition, &ActiveCamera)>,
window: Single<Window>,
global_light: Single<GlobalLight>,
+ assets: Single<Assets>,
mut gl_objects: Local<GlobalGlObjects>,
mut actions: Actions,
)
{
- let Some((camera, camera_pos, _)) = camera_query.iter().next() else {
- #[cfg(feature = "debug")]
+ let Some((camera, camera_world_pos, _)) = camera_query.iter().next() else {
tracing::warn!("No current camera. Nothing will be rendered");
return;
};
- let point_lights = point_light_query
- .iter()
- .map(|(point_light,)| point_light)
- .collect::<Vec<_>>();
-
let directional_lights = directional_lights.iter().collect::<Vec<_>>();
let GlobalGlObjects {
shader_program,
textures: gl_textures,
+ default_1x1_texture: default_1x1_gl_texture,
} = &mut *gl_objects;
let shader_program =
@@ -151,33 +177,31 @@ fn render(
clear_buffers(BufferClearMask::COLOR | BufferClearMask::DEPTH);
- for (
- entity_index,
- (mesh, material, material_flags, position, scale, draw_flags, gl_objects),
- ) in query.iter().enumerate()
+ 'subject_loop: for (
+ euid,
+ (model, material_flags, position, scale, draw_flags, gl_objects),
+ ) in query.iter_with_euids()
{
+ let Some(model_data) = assets.get(&model.asset_handle) else {
+ tracing::trace!("Missing model asset");
+ continue;
+ };
+
let material_flags = material_flags
.map(|material_flags| material_flags.clone())
.unwrap_or_default();
- let new_gl_objects;
-
- let gl_objects = if let Some(gl_objects) = gl_objects.as_deref() {
- gl_objects
- } else {
- // TODO: Account for when meshes are changed
- let gl_objects = GlObjects::new(&mesh);
-
- new_gl_objects = Some(gl_objects.clone());
-
- actions.add_components(
- query.get_entity_uid(entity_index).unwrap(),
- (gl_objects,),
- );
-
- &*new_gl_objects.unwrap()
+ let gl_objs = match gl_objects.as_deref() {
+ Some(gl_objs) => RefOrValue::Ref(gl_objs),
+ None => RefOrValue::Value(Some(GlObjects::new(&model_data.mesh))),
};
+ defer!(|gl_objs| {
+ if let RefOrValue::Value(opt_gl_objs) = gl_objs {
+ actions.add_components(euid, (opt_gl_objs.take().unwrap(),));
+ };
+ });
+
apply_transformation_matrices(
Transformation {
position: position.map(|pos| *pos).unwrap_or_default().position,
@@ -185,37 +209,82 @@ fn render(
},
shader_program,
&camera,
- &camera_pos,
+ &camera_world_pos,
window.size().expect("Failed to get window size"),
);
+ if model_data.materials.len() > 1 {
+ tracing::warn!(concat!(
+ "Multiple model materials are not supported ",
+ "so only the first material will be used"
+ ));
+ }
+
+ let material = match model_data.materials.values().next() {
+ Some(material) => material,
+ None => {
+ tracing::warn!("Model has no materials. Using default material");
+
+ &Material::default()
+ }
+ };
+
apply_light(
&material,
&material_flags,
&global_light,
shader_program,
- point_lights.as_slice(),
+ (point_light_query.iter(), point_light_query.iter().count()),
directional_lights
.iter()
.map(|(dir_light,)| &**dir_light)
.collect::<Vec<_>>()
.as_slice(),
- &camera_pos,
+ &camera_world_pos,
);
- for texture in &material.textures {
- let gl_texture = gl_textures
- .entry(texture.id())
- .or_insert_with(|| create_gl_texture(texture));
-
- let texture_unit =
- TextureUnit::from_texture_id(texture.id()).unwrap_or_else(|| {
- panic!("Texture id {} is a invalid texture unit", texture.id());
+ 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 gl_texture = default_1x1_gl_texture.get_or_insert_with(|| {
+ create_gl_texture(
+ &Image::from_color(1, Color::WHITE_U8),
+ &TextureProperties::default(),
+ )
});
- set_active_texture_unit(texture_unit);
+ gl_texture.bind_to_texture_unit(texture_unit);
- gl_texture.bind();
+ continue;
+ };
+
+ let texture_image_asset_id = texture.asset_handle.id();
+
+ let gl_texture = match gl_textures.get(&texture_image_asset_id) {
+ Some(gl_texture) => gl_texture,
+ None => {
+ let Some(image) = assets.get::<Image>(&texture.asset_handle) else {
+ tracing::trace!("Missing texture asset");
+ continue 'subject_loop;
+ };
+
+ gl_textures.insert(
+ texture_image_asset_id,
+ create_gl_texture(image, &texture.properties),
+ );
+
+ gl_textures
+ .get(&texture.asset_handle.id())
+ .expect("Not possible")
+ }
+ };
+
+ gl_texture.bind_to_texture_unit(texture_unit);
}
shader_program.activate();
@@ -227,7 +296,7 @@ fn render(
);
}
- draw_mesh(gl_objects);
+ draw_mesh(gl_objs.get().unwrap());
if draw_flags.is_some() {
let default_polygon_mode_config = PolygonModeConfig::default();
@@ -244,7 +313,8 @@ fn render(
struct GlobalGlObjects
{
shader_program: Option<GlShaderProgram>,
- textures: HashMap<TextureId, GlTexture>,
+ textures: HashMap<AssetId, GlTexture>,
+ default_1x1_texture: Option<GlTexture>,
}
fn set_viewport(position: Vec2<u32>, size: Dimens<u32>)
@@ -252,20 +322,11 @@ fn set_viewport(position: Vec2<u32>, size: Dimens<u32>)
crate::opengl::set_viewport(position, size);
}
-#[cfg(feature = "debug")]
fn initialize_debug()
{
- use crate::opengl::debug::{
- enable_debug_output,
- set_debug_message_callback,
- set_debug_message_control,
- MessageIdsAction,
- };
-
enable_debug_output();
set_debug_message_callback(opengl_debug_message_cb);
-
set_debug_message_control(None, None, None, &[], MessageIdsAction::Disable);
}
@@ -274,23 +335,37 @@ fn draw_mesh(gl_objects: &GlObjects)
gl_objects.vertex_arr.bind();
if gl_objects.index_buffer.is_some() {
- VertexArray::draw_elements(PrimitiveKind::Triangles, 0, gl_objects.index_cnt);
+ VertexArray::draw_elements(PrimitiveKind::Triangles, 0, gl_objects.element_cnt);
} else {
- VertexArray::draw_arrays(PrimitiveKind::Triangles, 0, 3);
+ VertexArray::draw_arrays(PrimitiveKind::Triangles, 0, gl_objects.element_cnt);
}
}
-fn create_gl_texture(texture: &Texture) -> GlTexture
+fn create_gl_texture(image: &Image, texture_properties: &TextureProperties) -> GlTexture
{
let mut gl_texture = GlTexture::new();
gl_texture.generate(
- *texture.dimensions(),
- texture.image().as_bytes(),
- texture.pixel_data_format(),
+ image.dimensions(),
+ image.as_bytes(),
+ match image.color_type() {
+ ImageColorType::Rgb8 => GlTexturePixelDataFormat::Rgb8,
+ ImageColorType::Rgba8 => GlTexturePixelDataFormat::Rgba8,
+ _ => {
+ unimplemented!();
+ }
+ },
);
- gl_texture.apply_properties(texture.properties());
+ gl_texture.set_wrap(texture_wrapping_to_gl(texture_properties.wrap));
+
+ gl_texture.set_magnifying_filter(texture_filtering_to_gl(
+ texture_properties.magnifying_filter,
+ ));
+
+ gl_texture.set_minifying_filter(texture_filtering_to_gl(
+ texture_properties.minifying_filter,
+ ));
gl_texture
}
@@ -361,19 +436,18 @@ fn get_glsl_shader_content(path: &Path) -> Result<Vec<u8>, std::io::Error>
struct GlObjects
{
/// Vertex and index buffer has to live as long as the vertex array
- vertex_buffer: Buffer<Vertex>,
+ _vertex_buffer: Buffer<Vertex>,
index_buffer: Option<Buffer<u32>>,
- index_cnt: u32,
+ element_cnt: u32,
vertex_arr: VertexArray,
}
impl GlObjects
{
- #[cfg_attr(feature = "debug", tracing::instrument(skip_all))]
+ #[tracing::instrument(skip_all)]
fn new(mesh: &Mesh) -> Self
{
- #[cfg(feature = "debug")]
tracing::trace!(
"Creating vertex array, vertex buffer{}",
if mesh.indices().is_some() {
@@ -386,7 +460,13 @@ impl GlObjects
let mut vertex_arr = VertexArray::new();
let mut vertex_buffer = Buffer::new();
- vertex_buffer.store(mesh.vertices(), BufferUsage::Static);
+ vertex_buffer.store_mapped(mesh.vertices(), BufferUsage::Static, |vertex| {
+ Vertex {
+ pos: vertex.pos,
+ texture_coords: vertex.texture_coords,
+ normal: vertex.normal,
+ }
+ });
vertex_arr.bind_vertex_buffer(0, &vertex_buffer, 0);
@@ -417,78 +497,77 @@ impl GlObjects
vertex_arr.bind_element_buffer(&index_buffer);
return Self {
- vertex_buffer,
+ _vertex_buffer: vertex_buffer,
index_buffer: Some(index_buffer),
- index_cnt: indices.len().try_into().unwrap(),
+ element_cnt: indices
+ .len()
+ .try_into()
+ .expect("Mesh index count does not fit into a 32-bit unsigned int"),
vertex_arr,
};
}
Self {
- vertex_buffer,
+ _vertex_buffer: vertex_buffer,
index_buffer: None,
- index_cnt: 0,
+ element_cnt: mesh
+ .vertices()
+ .len()
+ .try_into()
+ .expect("Mesh vertex count does not fit into a 32-bit unsigned int"),
vertex_arr,
}
}
-
- pub fn clone(&self) -> NeverDrop<Self>
- {
- NeverDrop::new(Self {
- // SAFETY: The vertex buffer will never become dropped (NeverDrop ensures it)
- vertex_buffer: unsafe { self.vertex_buffer.clone_weak() },
- index_buffer: self
- .index_buffer
- .as_ref()
- // SAFETY: The index buffer will never become dropped (NeverDrop ensures
- // it)
- .map(|index_buffer| unsafe { index_buffer.clone_weak() }),
- index_cnt: self.index_cnt,
- // SAFETY: The vertex array will never become dropped (NeverDrop ensures it)
- vertex_arr: unsafe { self.vertex_arr.clone_unsafe() },
- })
- }
}
fn apply_transformation_matrices(
transformation: Transformation,
gl_shader_program: &mut GlShaderProgram,
camera: &Camera,
- camera_pos: &Position,
+ camera_world_pos: &WorldPosition,
window_size: Dimens<u32>,
)
{
gl_shader_program
- .set_uniform_matrix_4fv(c"model", &create_transformation_matrix(transformation));
+ .set_uniform(c"model", &create_transformation_matrix(transformation));
- let view = create_view(camera, camera_pos);
+ let view_matrix = create_view_matrix(camera, &camera_world_pos.position);
- gl_shader_program.set_uniform_matrix_4fv(c"view", &view);
+ gl_shader_program.set_uniform(c"view", &view_matrix);
#[allow(clippy::cast_precision_loss)]
- let projection = match &camera.projection {
- Projection::Perspective(perspective) => new_perspective_matrix(
- perspective,
+ 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_matrix_4fv(c"projection", &projection);
+ gl_shader_program.set_uniform(c"projection", &proj_matrix);
}
-fn apply_light<PointLightHolder>(
+fn apply_light<'point_light>(
material: &Material,
material_flags: &MaterialFlags,
global_light: &GlobalLight,
gl_shader_program: &mut GlShaderProgram,
- point_lights: &[PointLightHolder],
+ (point_light_iter, point_light_cnt): (
+ impl Iterator<
+ Item = (
+ ComponentHandle<'point_light, PointLight>,
+ ComponentHandle<'point_light, WorldPosition>,
+ ),
+ >,
+ usize,
+ ),
directional_lights: &[&DirectionalLight],
- camera_pos: &Position,
-) where
- PointLightHolder: Deref<Target = PointLight>,
+ camera_world_pos: &WorldPosition,
+)
{
debug_assert!(
- point_lights.len() < 64,
+ point_light_cnt < 64,
"Shader cannot handle more than 64 point lights"
);
@@ -498,7 +577,7 @@ fn apply_light<PointLightHolder>(
);
for (dir_light_index, dir_light) in directional_lights.iter().enumerate() {
- gl_shader_program.set_uniform_vec_3fv(
+ gl_shader_program.set_uniform(
&create_light_uniform_name(
"directional_lights",
dir_light_index,
@@ -518,71 +597,68 @@ fn apply_light<PointLightHolder>(
// There probably won't be more than 2147483648 directional lights
#[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)]
gl_shader_program
- .set_uniform_1i(c"directional_light_cnt", directional_lights.len() as i32);
+ .set_uniform(c"directional_light_cnt", &(directional_lights.len() as i32));
- for (point_light_index, point_light) in point_lights.iter().enumerate() {
- gl_shader_program.set_uniform_vec_3fv(
+ for (point_light_index, (point_light, point_light_world_pos)) in
+ point_light_iter.enumerate()
+ {
+ gl_shader_program.set_uniform(
&create_light_uniform_name("point_lights", point_light_index, "position"),
- &point_light.position,
+ &(point_light_world_pos.position + point_light.local_position),
);
set_light_phong_uniforms(
gl_shader_program,
"point_lights",
point_light_index,
- &**point_light,
+ &*point_light,
);
set_light_attenuation_uniforms(
gl_shader_program,
"point_lights",
point_light_index,
- point_light,
+ &*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_1i(c"point_light_cnt", point_lights.len() as i32);
+ gl_shader_program.set_uniform(c"point_light_cnt", &(point_light_cnt as i32));
- gl_shader_program.set_uniform_vec_3fv(
+ gl_shader_program.set_uniform(
c"material.ambient",
- &if material_flags.use_ambient_color {
+ &Vec3::from(if material_flags.use_ambient_color {
material.ambient.clone()
} else {
global_light.ambient.clone()
- }
- .into(),
+ }),
);
gl_shader_program
- .set_uniform_vec_3fv(c"material.diffuse", &material.diffuse.clone().into());
+ .set_uniform(c"material.diffuse", &Vec3::from(material.diffuse.clone()));
#[allow(clippy::cast_possible_wrap)]
gl_shader_program
- .set_uniform_vec_3fv(c"material.specular", &material.specular.clone().into());
+ .set_uniform(c"material.specular", &Vec3::from(material.specular.clone()));
#[allow(clippy::cast_possible_wrap)]
- gl_shader_program.set_uniform_1i(
- c"material.ambient_map",
- material.ambient_map.into_inner() as i32,
- );
+ gl_shader_program
+ .set_uniform(c"material.ambient_map", &(AMBIENT_MAP_TEXTURE_UNIT as i32));
#[allow(clippy::cast_possible_wrap)]
- gl_shader_program.set_uniform_1i(
- c"material.diffuse_map",
- material.diffuse_map.into_inner() as i32,
- );
+ gl_shader_program
+ .set_uniform(c"material.diffuse_map", &(DIFFUSE_MAP_TEXTURE_UNIT as i32));
#[allow(clippy::cast_possible_wrap)]
- gl_shader_program.set_uniform_1i(
+ gl_shader_program.set_uniform(
c"material.specular_map",
- material.specular_map.into_inner() as i32,
+ &(SPECULAR_MAP_TEXTURE_UNIT as i32),
);
- gl_shader_program.set_uniform_1fv(c"material.shininess", material.shininess);
+ gl_shader_program.set_uniform(c"material.shininess", &material.shininess);
- gl_shader_program.set_uniform_vec_3fv(c"view_pos", &camera_pos.position);
+ gl_shader_program.set_uniform(c"view_pos", &camera_world_pos.position);
}
fn set_light_attenuation_uniforms(
@@ -592,27 +668,27 @@ fn set_light_attenuation_uniforms(
light: &PointLight,
)
{
- gl_shader_program.set_uniform_1fv(
+ gl_shader_program.set_uniform(
&create_light_uniform_name(
light_array,
light_index,
"attenuation_props.constant",
),
- light.attenuation_params.constant,
+ &light.attenuation_params.constant,
);
- gl_shader_program.set_uniform_1fv(
+ gl_shader_program.set_uniform(
&create_light_uniform_name(light_array, light_index, "attenuation_props.linear"),
- light.attenuation_params.linear,
+ &light.attenuation_params.linear,
);
- gl_shader_program.set_uniform_1fv(
+ gl_shader_program.set_uniform(
&create_light_uniform_name(
light_array,
light_index,
"attenuation_props.quadratic",
),
- light.attenuation_params.quadratic,
+ &light.attenuation_params.quadratic,
);
}
@@ -623,14 +699,14 @@ fn set_light_phong_uniforms(
light: &impl Light,
)
{
- gl_shader_program.set_uniform_vec_3fv(
+ gl_shader_program.set_uniform(
&create_light_uniform_name(light_array, light_index, "phong.diffuse"),
- &light.diffuse().clone().into(),
+ &Vec3::from(light.diffuse().clone()),
);
- gl_shader_program.set_uniform_vec_3fv(
+ gl_shader_program.set_uniform(
&create_light_uniform_name(light_array, light_index, "phong.specular"),
- &light.specular().clone().into(),
+ &Vec3::from(light.specular().clone()),
);
}
@@ -679,16 +755,15 @@ fn create_light_uniform_name(
}
}
-fn create_view(camera: &Camera, camera_pos: &Position) -> Matrix<f32, 4, 4>
+fn create_view_matrix(camera: &Camera, camera_pos: &Vec3<f32>) -> Matrix<f32, 4, 4>
{
let mut view = Matrix::new();
- view.look_at(&camera_pos.position, &camera.target, &camera.global_up);
+ view.look_at(&camera_pos, &camera.target, &camera.global_up);
view
}
-#[cfg(feature = "debug")]
#[tracing::instrument(skip_all)]
fn opengl_debug_message_cb(
source: MessageSource,
@@ -747,3 +822,23 @@ fn create_transformation_matrix(transformation: Transformation) -> Matrix<f32, 4
matrix
}
+
+#[inline]
+fn texture_wrapping_to_gl(texture_wrapping: TextureWrapping) -> GlTextureWrapping
+{
+ match texture_wrapping {
+ TextureWrapping::Repeat => GlTextureWrapping::Repeat,
+ TextureWrapping::MirroredRepeat => GlTextureWrapping::MirroredRepeat,
+ TextureWrapping::ClampToEdge => GlTextureWrapping::ClampToEdge,
+ TextureWrapping::ClampToBorder => GlTextureWrapping::ClampToBorder,
+ }
+}
+
+#[inline]
+fn texture_filtering_to_gl(texture_filtering: TextureFiltering) -> GlTextureFiltering
+{
+ match texture_filtering {
+ TextureFiltering::Linear => GlTextureFiltering::Linear,
+ TextureFiltering::Nearest => GlTextureFiltering::Nearest,
+ }
+}
diff --git a/engine/src/renderer/opengl/glsl/light.glsl b/engine/src/renderer/opengl/glsl/light.glsl
index 1bc23a4..f12b5fe 100644
--- a/engine/src/renderer/opengl/glsl/light.glsl
+++ b/engine/src/renderer/opengl/glsl/light.glsl
@@ -80,10 +80,10 @@ vec3 calc_specular_light(
{
vec3 view_direction = normalize(view_pos - frag_pos);
- vec3 reflect_direction = reflect(-light_dir, norm);
+ vec3 halfway_direction = normalize(light_dir + view_direction);
float spec =
- pow(max(dot(view_direction, reflect_direction), 0.0), material.shininess);
+ pow(max(dot(norm, halfway_direction), 0.0), material.shininess);
return light_phong.specular * (
spec * (vec3(texture(material.specular_map, texture_coords)) * material.specular)
diff --git a/engine/src/renderer/opengl/vertex.rs b/engine/src/renderer/opengl/vertex.rs
new file mode 100644
index 0000000..499b94b
--- /dev/null
+++ b/engine/src/renderer/opengl/vertex.rs
@@ -0,0 +1,64 @@
+use crate::vector::{Vec2, Vec3};
+
+#[derive(Debug, Clone)]
+#[repr(C)]
+pub struct Vertex
+{
+ pub pos: Vec3<f32>,
+ pub texture_coords: Vec2<f32>,
+ pub normal: Vec3<f32>,
+}
+
+impl Vertex
+{
+ pub fn attrs() -> &'static [Attribute]
+ {
+ #[allow(clippy::cast_possible_truncation)]
+ &[
+ Attribute {
+ index: 0,
+ component_type: AttributeComponentType::Float,
+ component_cnt: AttributeComponentCnt::Three,
+ component_size: size_of::<f32>() as u32,
+ },
+ Attribute {
+ index: 1,
+ component_type: AttributeComponentType::Float,
+ component_cnt: AttributeComponentCnt::Two,
+ component_size: size_of::<f32>() as u32,
+ },
+ Attribute {
+ index: 2,
+ component_type: AttributeComponentType::Float,
+ component_cnt: AttributeComponentCnt::Three,
+ component_size: size_of::<f32>() as u32,
+ },
+ ]
+ }
+}
+
+#[derive(Debug)]
+pub struct Attribute
+{
+ pub index: u32,
+ pub component_type: AttributeComponentType,
+ pub component_cnt: AttributeComponentCnt,
+ pub component_size: u32,
+}
+
+#[derive(Debug)]
+pub enum AttributeComponentType
+{
+ Float,
+}
+
+#[derive(Debug, Clone, Copy)]
+#[repr(u32)]
+#[allow(dead_code)]
+pub enum AttributeComponentCnt
+{
+ One = 1,
+ Two = 2,
+ Three = 3,
+ Four = 4,
+}