feat: frame constants & camera component #62
					 27 changed files with 167 additions and 318 deletions
				
			
		|  | @ -1,21 +1,26 @@ | ||||||
| #version 450 core | #version 450 core | ||||||
| 
 | 
 | ||||||
| vec2 positions[3] = vec2[]( | layout(push_constant ) uniform pc { | ||||||
|     vec2(0.0, -0.5), |  mat4 view_projection; | ||||||
|     vec2(0.5, 0.5), | }; | ||||||
|     vec2(-0.5, 0.5) | 
 | ||||||
|  | vec3 positions[3] = vec3[]( | ||||||
|  |     vec3(0.0, -0.5, 0.5), | ||||||
|  |     vec3(0.5, 0.5, 0.5), | ||||||
|  |     vec3(-0.5, 0.5, 0.5) | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| vec3 colors[3] = vec3[]( | vec3 colors[3] = vec3[]( | ||||||
|     vec3(1.0, 0.0, 0.0), |     vec3(0.0, 0.0, 0.0), | ||||||
|     vec3(0.0, 1.0, 0.0), |     vec3(0.0, 0.0, 0.0), | ||||||
|     vec3(0.0, 0.0, 1.0) |     vec3(0.0, 0.0, 0.0) | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| layout(location = 0) out vec3 out_frag_color; | layout(location = 0) out vec3 out_frag_color; | ||||||
| 
 | 
 | ||||||
| void main()  | void main()  | ||||||
| { | { | ||||||
|     gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); |     gl_Position = view_projection * vec4(positions[gl_VertexIndex], 1.0); | ||||||
|     out_frag_color = colors[gl_VertexIndex]; |     out_frag_color = colors[gl_VertexIndex]; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  |  | ||||||
										
											Binary file not shown.
										
									
								
							|  | @ -1,3 +1,3 @@ | ||||||
| add_library_module(camera camera.cpp scene.cpp) | add_library_module(camera) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(camera PUBLIC math) | target_link_libraries(camera INTERFACE math) | ||||||
|  |  | ||||||
|  | @ -1,6 +0,0 @@ | ||||||
| #include <camera/camera.hpp> |  | ||||||
| 
 |  | ||||||
| namespace lt { |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,84 +0,0 @@ | ||||||
| #include <camera/camera.hpp> |  | ||||||
| #include <camera/component.hpp> |  | ||||||
| #include <math/algebra.hpp> |  | ||||||
| #include <math/trig.hpp> |  | ||||||
| 
 |  | ||||||
| namespace lt { |  | ||||||
| 
 |  | ||||||
| SceneCamera::SceneCamera() |  | ||||||
|     : m_orthographic_specification { .size = 1000.0f, .near_plane = -1.0f, .far_plane = 10000.0f } |  | ||||||
|     , m_perspective_specification { .vertical_fov = math::radians(45.0f), |  | ||||||
| 	                                .near_plane = 0.01f, |  | ||||||
| 	                                .far_plane = 10000.0f } |  | ||||||
|     , m_aspect_ratio(16.0f / 9.0f) |  | ||||||
| 
 |  | ||||||
| { |  | ||||||
| 	calculate_projection(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SceneCamera::set_viewport_size(unsigned int width, unsigned int height) |  | ||||||
| { |  | ||||||
| 	m_aspect_ratio = static_cast<float>(width) / static_cast<float>(height); |  | ||||||
| 	calculate_projection(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SceneCamera::set_projection_type(ProjectionType projection_type) |  | ||||||
| { |  | ||||||
| 	m_projection_type = projection_type; |  | ||||||
| 	calculate_projection(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SceneCamera::set_orthographic_size(float size) |  | ||||||
| { |  | ||||||
| 	m_orthographic_specification.size = size; |  | ||||||
| 	calculate_projection(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SceneCamera::set_orthographic_far_plane(float far_plane) |  | ||||||
| { |  | ||||||
| 	m_orthographic_specification.far_plane = far_plane; |  | ||||||
| 	calculate_projection(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SceneCamera::set_orthographic_near_plane(float near_plane) |  | ||||||
| { |  | ||||||
| 	m_orthographic_specification.near_plane = near_plane; |  | ||||||
| 	calculate_projection(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SceneCamera::set_perspective_vertical_fov(float vertical_fov) |  | ||||||
| { |  | ||||||
| 	m_perspective_specification.vertical_fov = vertical_fov; |  | ||||||
| 	calculate_projection(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SceneCamera::set_perspective_far_plane(float far_plane) |  | ||||||
| { |  | ||||||
| 	m_perspective_specification.far_plane = far_plane; |  | ||||||
| 	calculate_projection(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SceneCamera::set_perspective_near_plane(float near_plane) |  | ||||||
| { |  | ||||||
| 	m_perspective_specification.near_plane = near_plane; |  | ||||||
| 	calculate_projection(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SceneCamera::calculate_projection() |  | ||||||
| { |  | ||||||
| 	// TODO(Light): implement ortho perspective
 |  | ||||||
| 	if (m_projection_type == ProjectionType::Orthographic) |  | ||||||
| 	{ |  | ||||||
| 		// throw std::runtime_error { "ortho perspective not supported yet" };
 |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// defaults to perspective for now...
 |  | ||||||
| 	m_projection = math::perspective( |  | ||||||
| 	    m_perspective_specification.vertical_fov, |  | ||||||
| 	    m_aspect_ratio, |  | ||||||
| 	    m_perspective_specification.near_plane, |  | ||||||
| 	    m_perspective_specification.far_plane |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace lt
 |  | ||||||
|  | @ -1,35 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <math/mat4.hpp> |  | ||||||
| #include <math/vec4.hpp> |  | ||||||
| 
 |  | ||||||
| namespace lt { |  | ||||||
| 
 |  | ||||||
| class Camera |  | ||||||
| { |  | ||||||
| public: |  | ||||||
| 	Camera() = default; |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_projection() const -> const math::mat4 & |  | ||||||
| 	{ |  | ||||||
| 		return m_projection; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_background_color() const -> const math::vec4 & |  | ||||||
| 	{ |  | ||||||
| 		return m_background_color; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void set_background_color(const math::vec4 &color) |  | ||||||
| 	{ |  | ||||||
| 		m_background_color = color; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| protected: |  | ||||||
| 	math::mat4 m_projection; |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
| 	math::vec4 m_background_color = math::vec4(1.0f, 0.0f, 0.0f, 1.0f); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| } // namespace lt
 |  | ||||||
|  | @ -1,29 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <camera/scene.hpp> |  | ||||||
| 
 |  | ||||||
| namespace lt { |  | ||||||
| 
 |  | ||||||
| struct CameraComponent |  | ||||||
| { |  | ||||||
| 	CameraComponent() = default; |  | ||||||
| 
 |  | ||||||
| 	CameraComponent(const CameraComponent &) = default; |  | ||||||
| 
 |  | ||||||
| 	CameraComponent(SceneCamera _camera, bool _isPrimary = false) |  | ||||||
| 	    : camera(_camera) |  | ||||||
| 	    , isPrimary(_isPrimary) |  | ||||||
| 	{ |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	operator SceneCamera() const |  | ||||||
| 	{ |  | ||||||
| 		return camera; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	SceneCamera camera; |  | ||||||
| 
 |  | ||||||
| 	bool isPrimary {}; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| } // namespace lt
 |  | ||||||
							
								
								
									
										22
									
								
								modules/camera/public/components.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								modules/camera/public/components.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <math/mat4.hpp> | ||||||
|  | 
 | ||||||
|  | namespace lt::camera::components { | ||||||
|  | 
 | ||||||
|  | struct PerspectiveCamera | ||||||
|  | { | ||||||
|  | 	float vertical_fov {}; | ||||||
|  | 
 | ||||||
|  | 	float near_plane {}; | ||||||
|  | 
 | ||||||
|  | 	float far_plane {}; | ||||||
|  | 
 | ||||||
|  | 	float aspect_ratio {}; | ||||||
|  | 
 | ||||||
|  | 	math::vec4 background_color; | ||||||
|  | 
 | ||||||
|  | 	bool is_primary {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace lt::camera::components
 | ||||||
|  | @ -1,100 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <camera/camera.hpp> |  | ||||||
| 
 |  | ||||||
| namespace lt { |  | ||||||
| 
 |  | ||||||
| class SceneCamera: public Camera |  | ||||||
| { |  | ||||||
| public: |  | ||||||
| 	enum class ProjectionType |  | ||||||
| 	{ |  | ||||||
| 		Orthographic = 0, |  | ||||||
| 		Perspetcive = 1 |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	struct OrthographicSpecification |  | ||||||
| 	{ |  | ||||||
| 		float size; |  | ||||||
| 
 |  | ||||||
| 		float near_plane; |  | ||||||
| 
 |  | ||||||
| 		float far_plane; |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	struct PerspectiveSpecification |  | ||||||
| 	{ |  | ||||||
| 		float vertical_fov; |  | ||||||
| 
 |  | ||||||
| 		float near_plane; |  | ||||||
| 
 |  | ||||||
| 		float far_plane; |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	SceneCamera(); |  | ||||||
| 
 |  | ||||||
| 	void set_viewport_size(unsigned int width, unsigned int height); |  | ||||||
| 
 |  | ||||||
| 	void set_projection_type(ProjectionType projection_type); |  | ||||||
| 
 |  | ||||||
| 	void set_orthographic_size(float size); |  | ||||||
| 
 |  | ||||||
| 	void set_orthographic_far_plane(float far_plane); |  | ||||||
| 
 |  | ||||||
| 	void set_orthographic_near_plane(float near_plane); |  | ||||||
| 
 |  | ||||||
| 	void set_perspective_vertical_fov(float vertical_fov); |  | ||||||
| 
 |  | ||||||
| 	void set_perspective_far_plane(float far_plane); |  | ||||||
| 
 |  | ||||||
| 	void set_perspective_near_plane(float near_plane); |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_orthographic_size() const -> float |  | ||||||
| 	{ |  | ||||||
| 		return m_orthographic_specification.size; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_orthographic_far_plane() const -> float |  | ||||||
| 	{ |  | ||||||
| 		return m_orthographic_specification.far_plane; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_orthographic_near_plane() const -> float |  | ||||||
| 	{ |  | ||||||
| 		return m_orthographic_specification.near_plane; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_perspective_vertical_fov() const -> float |  | ||||||
| 	{ |  | ||||||
| 		return m_perspective_specification.vertical_fov; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_perspective_far_plane() const -> float |  | ||||||
| 	{ |  | ||||||
| 		return m_perspective_specification.far_plane; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_perspective_near_plane() const -> float |  | ||||||
| 	{ |  | ||||||
| 		return m_perspective_specification.near_plane; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_projection_type() const -> ProjectionType |  | ||||||
| 	{ |  | ||||||
| 		return m_projection_type; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
| 	OrthographicSpecification m_orthographic_specification; |  | ||||||
| 
 |  | ||||||
| 	PerspectiveSpecification m_perspective_specification; |  | ||||||
| 
 |  | ||||||
| 	float m_aspect_ratio; |  | ||||||
| 
 |  | ||||||
| 	ProjectionType m_projection_type { ProjectionType::Orthographic }; |  | ||||||
| 
 |  | ||||||
| 	void calculate_projection(); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| } // namespace lt
 |  | ||||||
|  | @ -31,25 +31,29 @@ namespace lt::math { | ||||||
|  * |  * | ||||||
|  * the 1 at [z][3] is to save the Z axis into the resulting W for perspective division. |  * the 1 at [z][3] is to save the Z axis into the resulting W for perspective division. | ||||||
|  * |  * | ||||||
|  * thanks to pikuma: https://www.youtube.com/watch?v=EqNcqBdrNyI
 |  * @ref Thanks to pikuma for explaining the math behind this: | ||||||
|  |  * https://www.youtube.com/watch?v=EqNcqBdrNyI
 | ||||||
|  */ |  */ | ||||||
| template<typename T> | template<typename T> | ||||||
| constexpr auto perspective(T field_of_view, T aspect_ratio, T z_near, T z_far) | constexpr auto perspective(T field_of_view, T aspect_ratio, T z_near, T z_far) | ||||||
| { | { | ||||||
| 	const T half_fov_tan = std::tan(field_of_view / static_cast<T>(2)); | 	const T half_fov_tan = std::tan(field_of_view / static_cast<T>(2)); | ||||||
| 
 | 
 | ||||||
| 	auto result = mat4_impl<T> { T { 0 } }; | 	auto result = mat4_impl<T>::identity(); | ||||||
| 
 | 
 | ||||||
| 	result[0][0] = T { 1 } / (aspect_ratio * half_fov_tan); | 	result[0][0] = T { 1 } / (aspect_ratio * half_fov_tan); | ||||||
| 
 | 	//
 | ||||||
| 	result[1][1] = T { 1 } / (half_fov_tan); | 	result[1][1] = T { 1 } / (half_fov_tan); | ||||||
| 
 | 	//
 | ||||||
| 	result[2][2] = -(z_far + z_near) / (z_far - z_near); | 	//	result[2][2] = -(z_far + z_near) / (z_far - z_near);
 | ||||||
| 
 | 	//
 | ||||||
|  | 	result[2][2] = z_far / (z_far - z_near); | ||||||
|  | 	//
 | ||||||
| 	result[2][3] = -T { 1 }; | 	result[2][3] = -T { 1 }; | ||||||
| 
 | 	//
 | ||||||
| 	result[3][2] = -(T { 2 } * z_far * z_near) / (z_far - z_near); | 	// result[3][2] = -(T { 2 } * z_far * z_near) / (z_far - z_near);
 | ||||||
| 
 | 	result[3][2] = -(z_far * z_near) / (z_far - z_near); | ||||||
|  | 	//
 | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ template<typename T = float> | ||||||
| struct mat4_impl | struct mat4_impl | ||||||
| { | { | ||||||
| 	using Column_T = vec4_impl<T>; | 	using Column_T = vec4_impl<T>; | ||||||
|  | 
 | ||||||
| 	constexpr explicit mat4_impl(T scalar = 0) | 	constexpr explicit mat4_impl(T scalar = 0) | ||||||
| 	    : values( | 	    : values( | ||||||
| 	          { | 	          { | ||||||
|  | @ -43,7 +44,7 @@ struct mat4_impl | ||||||
| 	{ | 	{ | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] constexpr auto identity() -> mat4_impl<T> | 	[[nodiscard]] static constexpr auto identity() -> mat4_impl<T> | ||||||
| 	{ | 	{ | ||||||
| 		return mat4_impl<T> { | 		return mat4_impl<T> { | ||||||
| 			{ 1 }, {},    {},    {},    //
 | 			{ 1 }, {},    {},    {},    //
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| add_library_module(libmirror) | add_library_module(libmirror) | ||||||
| target_link_libraries(libmirror INTERFACE app time input surface renderer) | target_link_libraries(libmirror INTERFACE app time input surface renderer | ||||||
|  |                                           camera) | ||||||
| 
 | 
 | ||||||
| add_test_module( | add_test_module( | ||||||
|     libmirror layers/editor_layer.test.cpp panels/asset_browser.test.cpp |     libmirror layers/editor_layer.test.cpp panels/asset_browser.test.cpp | ||||||
|  |  | ||||||
|  | @ -2,9 +2,11 @@ | ||||||
| #include <app/application.hpp> | #include <app/application.hpp> | ||||||
| #include <app/entrypoint.hpp> | #include <app/entrypoint.hpp> | ||||||
| #include <app/system.hpp> | #include <app/system.hpp> | ||||||
|  | #include <camera/components.hpp> | ||||||
| #include <ecs/entity.hpp> | #include <ecs/entity.hpp> | ||||||
| #include <input/components.hpp> | #include <input/components.hpp> | ||||||
| #include <input/system.hpp> | #include <input/system.hpp> | ||||||
|  | #include <math/trig.hpp> | ||||||
| #include <math/vec2.hpp> | #include <math/vec2.hpp> | ||||||
| #include <memory/reference.hpp> | #include <memory/reference.hpp> | ||||||
| #include <memory/scope.hpp> | #include <memory/scope.hpp> | ||||||
|  | @ -66,13 +68,18 @@ public: | ||||||
| 			const auto &[x, y] = surface.get_position(); | 			const auto &[x, y] = surface.get_position(); | ||||||
| 			const auto &[width, height] = surface.get_resolution(); | 			const auto &[width, height] = surface.get_resolution(); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 			if (input.get_action(m_quit_action_key).state == State::active) | 			if (input.get_action(m_quit_action_key).state == State::active) | ||||||
| 			{ | 			{ | ||||||
| 				should_quit = true; | 				should_quit = true; | ||||||
| 			} | 			} | ||||||
| 			if (input.get_action(m_debug_action_keys[0]).state == State::active) | 			if (input.get_action(m_debug_action_keys[0]).state == State::active) | ||||||
| 			{ | 			{ | ||||||
| 				surface.push_request(surface::ModifyPositionRequest({ x + 5, y + 5 })); | 				for (auto &[id, camera] : | ||||||
|  | 				     m_registry->view<lt::camera::components::PerspectiveCamera>()) | ||||||
|  | 				{ | ||||||
|  | 					camera.vertical_fov += (static_cast<float>(tick.delta_time.count()) * 40.0f); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (input.get_action(m_debug_action_keys[1]).state == State::active) | 			if (input.get_action(m_debug_action_keys[1]).state == State::active) | ||||||
|  | @ -219,6 +226,20 @@ public: | ||||||
| 		        .callback = &renderer_callback, | 		        .callback = &renderer_callback, | ||||||
| 		        .user_data = this, | 		        .user_data = this, | ||||||
| 		    } }); | 		    } }); | ||||||
|  | 
 | ||||||
|  | 		m_camera_id = m_editor_registry->create_entity(); | ||||||
|  | 
 | ||||||
|  | 		m_editor_registry->add( | ||||||
|  | 		    m_camera_id, | ||||||
|  | 		    camera::components::PerspectiveCamera { | ||||||
|  | 		        .vertical_fov = math::radians(90.0f), | ||||||
|  | 		        .near_plane = 0.1f, | ||||||
|  | 		        .far_plane = 30.0, | ||||||
|  | 		        .aspect_ratio = 1.0f, | ||||||
|  | 		        .background_color = math::vec4(1.0, 0.0, 0.0, 1.0), | ||||||
|  | 		        .is_primary = true, | ||||||
|  | 		    } | ||||||
|  | 		); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void setup_input_system() | 	void setup_input_system() | ||||||
|  | @ -245,6 +266,8 @@ private: | ||||||
| 	memory::Ref<MirrorSystem> m_mirror_system; | 	memory::Ref<MirrorSystem> m_mirror_system; | ||||||
| 
 | 
 | ||||||
| 	lt::ecs::EntityId m_window = lt::ecs::null_entity; | 	lt::ecs::EntityId m_window = lt::ecs::null_entity; | ||||||
|  | 
 | ||||||
|  | 	lt::ecs::EntityId m_camera_id = lt::ecs::null_entity; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| auto app::create_application() -> memory::Scope<app::Application> | auto app::create_application() -> memory::Scope<app::Application> | ||||||
|  |  | ||||||
|  | @ -24,7 +24,13 @@ add_library_module( | ||||||
| 
 | 
 | ||||||
| target_link_libraries( | target_link_libraries( | ||||||
|     renderer |     renderer | ||||||
|     PUBLIC app ecs memory assets time bitwise |     PUBLIC app | ||||||
|  |            ecs | ||||||
|  |            memory | ||||||
|  |            assets | ||||||
|  |            time | ||||||
|  |            bitwise | ||||||
|  |            camera | ||||||
|     PRIVATE surface pthread) |     PRIVATE surface pthread) | ||||||
| 
 | 
 | ||||||
| add_test_module( | add_test_module( | ||||||
|  | @ -37,7 +43,7 @@ add_test_module( | ||||||
|     frontend/context/device.test.cpp |     frontend/context/device.test.cpp | ||||||
|     frontend/context/swapchain.test.cpp |     frontend/context/swapchain.test.cpp | ||||||
|     frontend/data/buffer.test.cpp |     frontend/data/buffer.test.cpp | ||||||
|     frontend/renderer/pass.test.cpp |     # frontend/renderer/pass.test.cpp | ||||||
|     frontend/renderer/renderer.test.cpp |     frontend/renderer/renderer.test.cpp | ||||||
|     # backend specific tests -- vk |     # backend specific tests -- vk | ||||||
|     backend/vk/context/instance.test.cpp) |     backend/vk/context/instance.test.cpp) | ||||||
|  |  | ||||||
|  | @ -276,9 +276,18 @@ void Device::unmap_memory(VkDeviceMemory memory) | ||||||
| 	return pass; | 	return pass; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [[nodiscard]] auto Device::create_pipeline_layout(VkPipelineLayoutCreateInfo info) const | [[nodiscard]] auto Device::create_pipeline_layout( | ||||||
|     -> VkPipelineLayout |     std::vector<VkPushConstantRange> push_constant_ranges | ||||||
|  | ) const -> VkPipelineLayout | ||||||
| { | { | ||||||
|  | 	auto info = VkPipelineLayoutCreateInfo { | ||||||
|  | 		.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | ||||||
|  | 		.setLayoutCount = 0u, | ||||||
|  | 		.pSetLayouts = nullptr, | ||||||
|  | 		.pushConstantRangeCount = static_cast<uint32_t>(push_constant_ranges.size()), | ||||||
|  | 		.pPushConstantRanges = push_constant_ranges.data(), | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| 	auto *pipeline_layout = VkPipelineLayout {}; | 	auto *pipeline_layout = VkPipelineLayout {}; | ||||||
| 	vkc(vk_create_pipeline_layout(m_device, &info, nullptr, &pipeline_layout)); | 	vkc(vk_create_pipeline_layout(m_device, &info, nullptr, &pipeline_layout)); | ||||||
| 	return pipeline_layout; | 	return pipeline_layout; | ||||||
|  |  | ||||||
|  | @ -118,8 +118,9 @@ public: | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto create_pass(VkRenderPassCreateInfo info) const -> VkRenderPass; | 	[[nodiscard]] auto create_pass(VkRenderPassCreateInfo info) const -> VkRenderPass; | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto create_pipeline_layout(VkPipelineLayoutCreateInfo info) const | 	[[nodiscard]] auto create_pipeline_layout( | ||||||
| 	    -> VkPipelineLayout; | 	    std::vector<VkPushConstantRange> push_constant_ranges | ||||||
|  | 	) const -> VkPipelineLayout; | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto create_shader_module(VkShaderModuleCreateInfo info) const -> VkShaderModule; | 	[[nodiscard]] auto create_shader_module(VkShaderModuleCreateInfo info) const -> VkShaderModule; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -87,6 +87,7 @@ PFN_vkCmdBindPipeline vk_cmd_bind_pipeline {}; | ||||||
| PFN_vkCmdDraw vk_cmd_draw {}; | PFN_vkCmdDraw vk_cmd_draw {}; | ||||||
| PFN_vkCmdSetViewport vk_cmd_set_viewport {}; | PFN_vkCmdSetViewport vk_cmd_set_viewport {}; | ||||||
| PFN_vkCmdSetScissor vk_cmd_set_scissors {}; | PFN_vkCmdSetScissor vk_cmd_set_scissors {}; | ||||||
|  | PFN_vkCmdPushConstants vk_cmd_push_constants {}; | ||||||
| 
 | 
 | ||||||
| PFN_vkCreateBuffer vk_create_buffer {}; | PFN_vkCreateBuffer vk_create_buffer {}; | ||||||
| PFN_vkDestroyBuffer vk_destroy_buffer {}; | PFN_vkDestroyBuffer vk_destroy_buffer {}; | ||||||
|  | @ -97,7 +98,6 @@ PFN_vkMapMemory vk_map_memory {}; | ||||||
| PFN_vkUnmapMemory vk_unmap_memory {}; | PFN_vkUnmapMemory vk_unmap_memory {}; | ||||||
| PFN_vkFreeMemory vk_free_memory {}; | PFN_vkFreeMemory vk_free_memory {}; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| PFN_vkResetCommandBuffer vk_reset_command_buffer {}; | PFN_vkResetCommandBuffer vk_reset_command_buffer {}; | ||||||
| 
 | 
 | ||||||
| PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {}; | PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {}; | ||||||
|  | @ -382,6 +382,7 @@ void Instance::load_device_functions_impl(VkDevice device) | ||||||
| 	load_fn(vk_cmd_draw, "vkCmdDraw"); | 	load_fn(vk_cmd_draw, "vkCmdDraw"); | ||||||
| 	load_fn(vk_cmd_set_viewport, "vkCmdSetViewport"); | 	load_fn(vk_cmd_set_viewport, "vkCmdSetViewport"); | ||||||
| 	load_fn(vk_cmd_set_scissors, "vkCmdSetScissor"); | 	load_fn(vk_cmd_set_scissors, "vkCmdSetScissor"); | ||||||
|  | 	load_fn(vk_cmd_push_constants, "vkCmdPushConstants"); | ||||||
| 	load_fn(vk_create_buffer, "vkCreateBuffer"); | 	load_fn(vk_create_buffer, "vkCreateBuffer"); | ||||||
| 	load_fn(vk_destroy_buffer, "vkDestroyBuffer"); | 	load_fn(vk_destroy_buffer, "vkDestroyBuffer"); | ||||||
| 	load_fn(vk_allocate_memory, "vkAllocateMemory"); | 	load_fn(vk_allocate_memory, "vkAllocateMemory"); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include <renderer/backend/vk/context/device.hpp> | #include <renderer/backend/vk/context/device.hpp> | ||||||
| #include <renderer/backend/vk/context/swapchain.hpp> | #include <renderer/backend/vk/context/swapchain.hpp> | ||||||
| #include <renderer/backend/vk/renderer/pass.hpp> | #include <renderer/backend/vk/renderer/pass.hpp> | ||||||
|  | #include <renderer/data/frame_constants.hpp> | ||||||
| 
 | 
 | ||||||
| namespace lt::renderer::vk { | namespace lt::renderer::vk { | ||||||
| 
 | 
 | ||||||
|  | @ -12,12 +13,12 @@ Pass::Pass( | ||||||
| ) | ) | ||||||
|     : m_device(static_cast<Device *>(device)) |     : m_device(static_cast<Device *>(device)) | ||||||
|     , m_layout(m_device->create_pipeline_layout( |     , m_layout(m_device->create_pipeline_layout( | ||||||
|           VkPipelineLayoutCreateInfo { |           std::vector<VkPushConstantRange> { | ||||||
|               .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |               VkPushConstantRange { | ||||||
|               .setLayoutCount = 0u, |                   .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, | ||||||
|               .pSetLayouts = nullptr, |                   .offset = 0u, | ||||||
|               .pushConstantRangeCount = 0u, |                   .size = sizeof(FrameConstants), | ||||||
|               .pPushConstantRanges = nullptr, |               }, | ||||||
|           } |           } | ||||||
|       )) |       )) | ||||||
| { | { | ||||||
|  | @ -112,7 +113,6 @@ Pass::Pass( | ||||||
| 		.blendConstants = { 0.0f, 0.0, 0.0, 0.0 }, | 		.blendConstants = { 0.0f, 0.0, 0.0, 0.0 }, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	auto attachment_description = VkAttachmentDescription { | 	auto attachment_description = VkAttachmentDescription { | ||||||
| 		.format = static_cast<Swapchain *>(swapchain)->get_format(), | 		.format = static_cast<Swapchain *>(swapchain)->get_format(), | ||||||
| 		.samples = VK_SAMPLE_COUNT_1_BIT, | 		.samples = VK_SAMPLE_COUNT_1_BIT, | ||||||
|  | @ -179,7 +179,6 @@ Pass::Pass( | ||||||
| 
 | 
 | ||||||
| 	m_framebuffers = static_cast<Swapchain *>(swapchain)->create_framebuffers_for_pass(m_pass); | 	m_framebuffers = static_cast<Swapchain *>(swapchain)->create_framebuffers_for_pass(m_pass); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	m_device->destroy_shader_module(vertex_module); | 	m_device->destroy_shader_module(vertex_module); | ||||||
| 	m_device->destroy_shader_module(fragment_module); | 	m_device->destroy_shader_module(fragment_module); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -39,6 +39,11 @@ public: | ||||||
| 		return m_pipeline; | 		return m_pipeline; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] auto get_layout() -> VkPipelineLayout | ||||||
|  | 	{ | ||||||
|  | 		return m_layout; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	[[nodiscard]] auto get_framebuffers() -> std::vector<VkFramebuffer> & | 	[[nodiscard]] auto get_framebuffers() -> std::vector<VkFramebuffer> & | ||||||
| 	{ | 	{ | ||||||
| 		return m_framebuffers; | 		return m_framebuffers; | ||||||
|  |  | ||||||
|  | @ -100,6 +100,7 @@ Renderer::~Renderer() | ||||||
| 	vk_reset_command_buffer(cmd, {}); | 	vk_reset_command_buffer(cmd, {}); | ||||||
| 	record_cmd(cmd, *image_idx); | 	record_cmd(cmd, *image_idx); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 	auto wait_stage = VkPipelineStageFlags { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; | 	auto wait_stage = VkPipelineStageFlags { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; | ||||||
| 	auto &submit_semaphore = m_submit_semaphores[*image_idx]; | 	auto &submit_semaphore = m_submit_semaphores[*image_idx]; | ||||||
| 	m_device->submit( | 	m_device->submit( | ||||||
|  | @ -149,6 +150,14 @@ void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx) | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	vkc(vk_begin_command_buffer(cmd, &cmd_begin_info)); | 	vkc(vk_begin_command_buffer(cmd, &cmd_begin_info)); | ||||||
|  | 	vk_cmd_push_constants( | ||||||
|  | 	    cmd, | ||||||
|  | 	    m_pass->get_layout(), | ||||||
|  | 	    VK_SHADER_STAGE_VERTEX_BIT, | ||||||
|  | 	    0u, | ||||||
|  | 	    sizeof(FrameConstants), | ||||||
|  | 	    &m_frame_constants | ||||||
|  | 	); | ||||||
| 
 | 
 | ||||||
| 	auto clear_value = VkClearValue { | 	auto clear_value = VkClearValue { | ||||||
| 			.color = {  | 			.color = {  | ||||||
|  | @ -181,7 +190,7 @@ void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx) | ||||||
| 	vk_cmd_set_viewport(cmd, 0, 1, &viewport); | 	vk_cmd_set_viewport(cmd, 0, 1, &viewport); | ||||||
| 
 | 
 | ||||||
| 	auto scissor = VkRect2D { | 	auto scissor = VkRect2D { | ||||||
| 		.offset = { 0u, 0u }, | 		.offset = { .x = 0u, .y = 0u }, | ||||||
| 		.extent = m_resolution, | 		.extent = m_resolution, | ||||||
| 	}; | 	}; | ||||||
| 	vk_cmd_set_scissors(cmd, 0, 1, &scissor); | 	vk_cmd_set_scissors(cmd, 0, 1, &scissor); | ||||||
|  |  | ||||||
|  | @ -29,6 +29,11 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void replace_swapchain(ISwapchain *swapchain) override; | 	void replace_swapchain(ISwapchain *swapchain) override; | ||||||
| 
 | 
 | ||||||
|  | 	void set_frame_constants(FrameConstants constants) override | ||||||
|  | 	{ | ||||||
|  | 		m_frame_constants = constants; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
| 	void record_cmd(VkCommandBuffer cmd, uint32_t image_idx); | 	void record_cmd(VkCommandBuffer cmd, uint32_t image_idx); | ||||||
| 
 | 
 | ||||||
|  | @ -51,6 +56,8 @@ private: | ||||||
| 	VkExtent2D m_resolution; | 	VkExtent2D m_resolution; | ||||||
| 
 | 
 | ||||||
| 	uint32_t m_max_frames_in_flight {}; | 	uint32_t m_max_frames_in_flight {}; | ||||||
|  | 
 | ||||||
|  | 	FrameConstants m_frame_constants; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace lt::renderer::vk
 | } // namespace lt::renderer::vk
 | ||||||
|  |  | ||||||
|  | @ -76,6 +76,7 @@ extern PFN_vkCmdBindPipeline vk_cmd_bind_pipeline; | ||||||
| extern PFN_vkCmdDraw vk_cmd_draw; | extern PFN_vkCmdDraw vk_cmd_draw; | ||||||
| extern PFN_vkCmdSetViewport vk_cmd_set_viewport; | extern PFN_vkCmdSetViewport vk_cmd_set_viewport; | ||||||
| extern PFN_vkCmdSetScissor vk_cmd_set_scissors; | extern PFN_vkCmdSetScissor vk_cmd_set_scissors; | ||||||
|  | extern PFN_vkCmdPushConstants vk_cmd_push_constants; | ||||||
| 
 | 
 | ||||||
| extern PFN_vkCreateBuffer vk_create_buffer; | extern PFN_vkCreateBuffer vk_create_buffer; | ||||||
| extern PFN_vkDestroyBuffer vk_destroy_buffer; | extern PFN_vkDestroyBuffer vk_destroy_buffer; | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ using ::lt::renderer::IMessenger; | ||||||
| 
 | 
 | ||||||
| Suite raii = "pass_raii"_suite = [] { | Suite raii = "pass_raii"_suite = [] { | ||||||
| 	Case { "happy path won't throw" } = [] { | 	Case { "happy path won't throw" } = [] { | ||||||
| 		auto fixture = Fixture_RendererSystem {}; | 		Fixture_ auto fixture = Fixture_RendererSystem {}; | ||||||
| 		auto &system = fixture.renderer_system(); | 		auto &system = fixture.renderer_system(); | ||||||
| 
 | 
 | ||||||
| 		std::ignore = lt::renderer::IPass::create( | 		std::ignore = lt::renderer::IPass::create( | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <memory/scope.hpp> | #include <memory/scope.hpp> | ||||||
| #include <renderer/api.hpp> | #include <renderer/api.hpp> | ||||||
|  | #include <renderer/data/frame_constants.hpp> | ||||||
| 
 | 
 | ||||||
| namespace lt::renderer { | namespace lt::renderer { | ||||||
| 
 | 
 | ||||||
|  | @ -41,6 +42,8 @@ public: | ||||||
| 	[[nodiscard]] virtual auto draw(uint32_t frame_idx) -> DrawResult = 0; | 	[[nodiscard]] virtual auto draw(uint32_t frame_idx) -> DrawResult = 0; | ||||||
| 
 | 
 | ||||||
| 	virtual void replace_swapchain(class ISwapchain *swapchain) = 0; | 	virtual void replace_swapchain(class ISwapchain *swapchain) = 0; | ||||||
|  | 
 | ||||||
|  | 	virtual void set_frame_constants(FrameConstants constants) = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace lt::renderer
 | } // namespace lt::renderer
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
|  | #include <camera/components.hpp> | ||||||
|  | #include <math/algebra.hpp> | ||||||
| #include <renderer/components/messenger.hpp> | #include <renderer/components/messenger.hpp> | ||||||
| #include <renderer/frontend/context/device.hpp> | #include <renderer/frontend/context/device.hpp> | ||||||
| #include <renderer/frontend/context/gpu.hpp> | #include <renderer/frontend/context/gpu.hpp> | ||||||
|  | @ -70,6 +72,23 @@ void System::tick(app::TickInfo tick) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	auto perspective = math::mat4::identity(); | ||||||
|  | 	for (auto [id, camera] : m_registry->view<lt::camera::components::PerspectiveCamera>()) | ||||||
|  | 	{ | ||||||
|  | 		if (camera.is_primary) | ||||||
|  | 		{ | ||||||
|  | 			perspective = math::perspective( | ||||||
|  | 			    camera.vertical_fov, | ||||||
|  | 			    camera.aspect_ratio, | ||||||
|  | 			    camera.near_plane, | ||||||
|  | 			    camera.far_plane | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	m_renderer->set_frame_constants({ .view_projection = perspective }); | ||||||
| 	if (m_renderer->draw(m_frame_idx) != IRenderer::DrawResult::success) | 	if (m_renderer->draw(m_frame_idx) != IRenderer::DrawResult::success) | ||||||
| 	{ | 	{ | ||||||
| 		m_swapchain.reset(); | 		m_swapchain.reset(); | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								modules/renderer/public/data/frame_constants.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								modules/renderer/public/data/frame_constants.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <math/mat4.hpp> | ||||||
|  | 
 | ||||||
|  | namespace lt::renderer { | ||||||
|  | 
 | ||||||
|  | struct FrameConstants | ||||||
|  | { | ||||||
|  | 	math::mat4 view_projection; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace lt::renderer
 | ||||||
|  | @ -55,31 +55,6 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void tick(app::TickInfo tick) override; | 	void tick(app::TickInfo tick) override; | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto get_surface() -> class ISurface * |  | ||||||
| 	{ |  | ||||||
| 		return m_surface.get(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_gpu() -> class IGpu * |  | ||||||
| 	{ |  | ||||||
| 		return m_gpu.get(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_device() -> class IDevice * |  | ||||||
| 	{ |  | ||||||
| 		return m_device.get(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_swapchain() -> class ISwapchain * |  | ||||||
| 	{ |  | ||||||
| 		return m_swapchain.get(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_renderer() -> class IRenderer * |  | ||||||
| 	{ |  | ||||||
| 		return m_renderer.get(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override | 	[[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override | ||||||
| 	{ | 	{ | ||||||
| 		return m_last_tick_result; | 		return m_last_tick_result; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue