diff --git a/.gitignore b/.gitignore index 21be2a1..587077d 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ fips-files/deploy/ .idea/ CMakeUserPresets.json #setup_surface(&window, false); + app.get_render_context()->setup_surface(&window); app.run(); return 0; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6f1a60..5dfd1b8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,12 @@ cmake_minimum_required(VERSION 3.15) project(mirage_core LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 26) +if (MSVC) + # MSVC编译器设置C++标准 + add_compile_options(/std:c++latest) + # 设置utf-8编码 + add_compile_options(/utf-8) +endif () find_package(Freetype REQUIRED) find_package(Eigen3 REQUIRED) diff --git a/src/core/render_context.h b/src/core/render_context.h index 1d86154..baebbda 100644 --- a/src/core/render_context.h +++ b/src/core/render_context.h @@ -1,9 +1,7 @@ #pragma once -#include "sokol/sokol_gfx.h" #include "misc/mirage_type.h" -#include -#include +#include "sokol/sokol_header.h" class mirage_window; @@ -13,10 +11,11 @@ public: virtual ~mirage_render_context() = default; virtual bool init() { return false; } + virtual void end_init() {} virtual void cleanup() { } virtual void tick(const duration_type& in_delta) = 0; virtual sg_environment get_environment() = 0; - virtual bool setup_surface(mirage_window* in_window, bool in_hdr) { return false; } + virtual bool setup_surface(mirage_window* in_window) { return false; } }; mirage_render_context* mirage_create_render_context(); diff --git a/src/core/render_elements.cpp b/src/core/render_elements.cpp new file mode 100644 index 0000000..ecf512a --- /dev/null +++ b/src/core/render_elements.cpp @@ -0,0 +1,274 @@ +#include "render_elements.h" +#include "shaders/mirage_rounded_rect.hlsl.h" + +template +void compute_rect_vertices(const Eigen::MatrixBase& in_pos, + const Eigen::MatrixBase& in_size, + Eigen::Matrix& positions, + float rotation_radians = 0.0f, + const Eigen::Vector2f& scale = Eigen::Vector2f(1.0f, 1.0f), + const Eigen::Vector2f& pivot = Eigen::Vector2f(0.5f, 0.5f)) { + // 计算缩放后的尺寸 + Eigen::Array2f scaled_size = in_size.array() * scale.array(); + + // 计算旋转矩阵 + const Eigen::Rotation2D rotation(rotation_radians); + const Eigen::Matrix2f rot_matrix = rotation.toRotationMatrix(); + + // 计算基于原点的矩形顶点(左上角在原点) + Eigen::Matrix rect_points; + rect_points.col(0) = Eigen::Vector2f(0, 0); // 左上 + rect_points.col(1) = Eigen::Vector2f(scaled_size.x(), 0); // 右上 + rect_points.col(2) = Eigen::Vector2f(0, scaled_size.y()); // 左下 + rect_points.col(3) = Eigen::Vector2f(scaled_size.x(), scaled_size.y()); // 右下 + + // 计算锚点偏移(相对于左上角) + const auto& pivot_offset = Eigen::Vector2f(scaled_size.x() * pivot.x(), + scaled_size.y() * pivot.y()); + + // 应用旋转(绕锚点旋转) + for (int i = 0; i < 4; ++i) { + // 将点移到锚点为中心 + Eigen::Vector2f centered = rect_points.col(i) - pivot_offset; + // 应用旋转 + rect_points.col(i) = rot_matrix * centered + pivot_offset; + // 添加位置偏移 + positions.col(i) = rect_points.col(i) + in_pos; + } +} + +// 开始新一帧 +void render_elements::begin_frame() { + vertices.clear(); + indices.clear(); + batches.clear(); + current_batch_index = -1; + current_key = batch_key{}; + draw_call_count = 0; + total_triangles = 0; +} + +// 设置渲染管线 +void render_elements::set_pipeline(sg_pipeline pipeline) { + batch_key new_key = current_key; + new_key.pipeline = pipeline; + ensure_batch_compatibility(new_key); +} + +// 设置纹理 +void render_elements::set_texture(sg_image image) { + batch_key new_key = current_key; + new_key.image = image; + ensure_batch_compatibility(new_key); +} + +// 确保批次兼容性 +void render_elements::ensure_batch_compatibility(const batch_key& key) { + // 如果当前没有批次或者渲染状态改变了,创建新批次 + if (current_batch_index < 0 || !(current_key == key)) { + current_key = key; + + draw_batch new_batch; + new_batch.key = key; + new_batch.vertex_start = vertices.size(); + new_batch.index_start = indices.size(); + + batches.push_back(new_batch); + current_batch_index = batches.size() - 1; + } +} + +// 添加矩形到当前批次 +void render_elements::add_rect_to_batch( + const Eigen::Vector2f& in_pos, + const Eigen::Vector2f& in_size, + const rect_color& in_color, + const mirage_vertex_param_t& in_param_a, + const mirage_vertex_param_t& in_param_b, + const mirage_vertex_param_t& in_param_c, + const rect_uv& in_uv, + float in_rotation_radians, + const Eigen::Vector2f& in_pivot, + const Eigen::Vector2f& in_scale) { + // 确保有活跃的批次 + if (current_batch_index < 0) { + set_pipeline(sg_pipeline{}); // 使用默认管线 + set_texture(sg_image{}); // 使用默认纹理 + } + + // 计算顶点位置 + Eigen::Matrix positions; + compute_rect_vertices(in_pos, in_size, positions, in_rotation_radians, in_pivot, in_scale); + + // 记录起始顶点索引 + uint32_t base_index = vertices.size(); + + // 添加顶点 + for (int i = 0; i < 4; ++i) { + auto& vertex = vertices.emplace_back(); + vertex.position = positions.col(i); + vertex.color = in_color[i]; + vertex.uv = in_uv[i]; + vertex.param_a = in_param_a; + vertex.param_b = in_param_b; + vertex.param_c = in_param_c; + } + + // 添加索引(两个三角形) + indices.push_back(base_index); + indices.push_back(base_index + 1); + indices.push_back(base_index + 2); + + indices.push_back(base_index + 1); + indices.push_back(base_index + 3); + indices.push_back(base_index + 2); + + // 更新当前批次的计数 + draw_batch& batch = batches[current_batch_index]; + batch.vertex_count = vertices.size() - batch.vertex_start; + batch.index_count = indices.size() - batch.index_start; + + // 更新统计信息 + total_triangles += 2; +} + +// 创建矩形(公开接口) +void render_elements::make_rect( + const Eigen::Vector2f& in_pos, + const Eigen::Vector2f& in_size, + const rect_color& in_color, + const mirage_vertex_param_t& in_param_a, + const mirage_vertex_param_t& in_param_b, + const mirage_vertex_param_t& in_param_c, + const rect_uv& in_uv, + float in_rotation_radians, + const Eigen::Vector2f& in_pivot, + const Eigen::Vector2f& in_scale) { + add_rect_to_batch(in_pos, + in_size, + in_color, + in_param_a, + in_param_b, + in_param_c, + in_uv, + in_rotation_radians, + in_pivot, + in_scale); +} + +void render_elements::make_rounded_rect(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, + const rect_color& in_color, const rect_uv& in_uv, const rect_round& in_round, + float in_rotation_radians, + const Eigen::Vector2f& in_pivot, const Eigen::Vector2f& in_scale) { + set_pipeline(rounded_rect_pipeline); + mirage_vertex_param_t param_a{ in_size }; + mirage_vertex_param_t param_b(in_round); + make_rect(in_pos, in_size, in_color, param_a, param_b, {}, in_uv, in_rotation_radians, in_scale, in_pivot); +} + +// 确保缓冲区容量 +void render_elements::ensure_buffer_capacity(uint32_t vertex_count, uint32_t index_count) { + // 如果现有缓冲区不够大,重新创建 + if (vertex_count > vertex_buffer_capacity) { + // 销毁旧缓冲区 + if (vertex_buffer.id != SG_INVALID_ID) { sg_destroy_buffer(vertex_buffer); } + + // 创建新缓冲区,容量翻倍以减少重新分配 + vertex_buffer_capacity = vertex_count * 2; + sg_buffer_desc vbuf_desc = {}; + vbuf_desc.size = vertex_buffer_capacity * sizeof(mirage_vertex_t); + vbuf_desc.usage = SG_USAGE_STREAM; + vertex_buffer = sg_make_buffer(&vbuf_desc); + } + + if (index_count > index_buffer_capacity) { + if (index_buffer.id != SG_INVALID_ID) { sg_destroy_buffer(index_buffer); } + + index_buffer_capacity = index_count * 2; + sg_buffer_desc ibuf_desc = {}; + ibuf_desc.size = index_buffer_capacity * sizeof(uint32_t); + ibuf_desc.usage = SG_USAGE_STREAM; + ibuf_desc.type = SG_BUFFERTYPE_INDEXBUFFER; + index_buffer = sg_make_buffer(&ibuf_desc); + } +} + +// 上传并绘制所有批次 +void render_elements::flush_batches() { + // 如果没有数据,直接返回 + if (vertices.empty() || indices.empty() || batches.empty()) { return; } + + // 确保缓冲区足够大 + ensure_buffer_capacity(vertices.size(), indices.size()); + + // 上传顶点和索引数据 + sg_update_buffer(vertex_buffer, sg_range{ vertices.data(), vertices.size() * sizeof(mirage_vertex_t) }); + sg_update_buffer(index_buffer, sg_range{ indices.data(), indices.size() * sizeof(uint32_t) }); + + // 绑定顶点和索引缓冲区 + sg_bindings bind = {}; + bind.vertex_buffers[0] = vertex_buffer; + bind.index_buffer = index_buffer; + + // 渲染每个批次 + for (const auto& batch: batches) { + // 设置纹理 + bind.images[0] = batch.key.image; + + // 绑定管线 + sg_apply_pipeline(batch.key.pipeline); + sg_apply_bindings(&bind); + + sg_apply_uniforms(0, SG_RANGE(projection_matrix)); + + // 绘制批次 + sg_draw(batch.index_start, batch.index_count, 1); + draw_call_count++; + } +} + +// 结束帧并提交所有批次 +void render_elements::end_frame() { flush_batches(); } + +// 析构函数 +render_elements::~render_elements() { + if (!sg_isvalid()) + return; + if (vertex_buffer.id != SG_INVALID_ID) { sg_destroy_buffer(vertex_buffer); } + if (index_buffer.id != SG_INVALID_ID) { sg_destroy_buffer(index_buffer); } +} + +void render_elements::create_resources() { + constexpr uint32_t default_vertex_buffer_size = 512; // 512kb + constexpr uint32_t default_index_buffer_size = 256; // 256kb + // 计算默认顶点, 使用default_vertex_buffer_size对齐到sizeof(mirage_vertex_t) + vertex_buffer_capacity = default_vertex_buffer_size * 1024 / sizeof(mirage_vertex_t); + index_buffer_capacity = default_index_buffer_size * 1024 / sizeof(uint32_t); + + // 创建顶点缓冲区 + sg_buffer_desc vbuf_desc = {}; + vbuf_desc.size = vertex_buffer_capacity * sizeof(mirage_vertex_t); + vbuf_desc.usage = SG_USAGE_STREAM; + vbuf_desc.type = SG_BUFFERTYPE_VERTEXBUFFER; + vertex_buffer = sg_make_buffer(&vbuf_desc); + + // 创建索引缓冲区 + sg_buffer_desc ibuf_desc = {}; + ibuf_desc.size = index_buffer_capacity * sizeof(mirage_triangle_t); + ibuf_desc.usage = SG_USAGE_STREAM; + ibuf_desc.type = SG_BUFFERTYPE_INDEXBUFFER; + index_buffer = sg_make_buffer(&ibuf_desc); +} + +void render_elements::load_mirage_pipelines() { +#ifdef MIRAGE_USE_HDR + auto format = MIRAGE_HDR_FORMAT; +#else + auto format = MIRAGE_PIXEL_FORMAT; +#endif + auto rounded_rect_shader = sg_make_shader(get_mirage_rounded_rect_shader_desc()); + auto rounded_rect_pipeline_desc = get_mirage_rounded_rect_pipeline_desc(rounded_rect_shader, + format, + 1); + rounded_rect_pipeline = sg_make_pipeline(rounded_rect_pipeline_desc); +} diff --git a/src/core/render_elements.h b/src/core/render_elements.h new file mode 100644 index 0000000..158628c --- /dev/null +++ b/src/core/render_elements.h @@ -0,0 +1,143 @@ +#pragma once + +#include "sokol/sokol_header.h" +#include "misc/color.h" +#include "misc/mirage_type.h" + +enum class draw_effect { +}; + +// 用于标识批次的键 +struct batch_key { + sg_pipeline pipeline{}; + sg_image image{}; + // 可选:添加其他影响状态的元素,如着色器、混合模式等 + + bool operator==(const batch_key& other) const { + return pipeline.id == other.pipeline.id && + image.id == other.image.id; + } + + bool operator<(const batch_key& other) const { + if (pipeline.id != other.pipeline.id) + return pipeline.id < other.pipeline.id; + return image.id < other.image.id; + } +}; + +// 表示一个绘制批次 +struct draw_batch { + batch_key key; + uint32_t vertex_start = 0; // 批次在顶点缓冲区中的起始索引 + uint32_t vertex_count = 0; // 批次包含的顶点数量 + uint32_t index_start = 0; // 批次在索引缓冲区中的起始索引 + uint32_t index_count = 0; // 批次包含的索引数量 +}; + +// 特化类型 +using rect_color = rect_quad; +using rect_uv = rect_quad; +using rect_round = rect_quad; + +// 为rect_uv提供默认构造函数特化 +template<> +inline rect_quad::rect_quad() : std::array{ + Eigen::Vector2f{ 0, 0 }, + Eigen::Vector2f{ 1, 0 }, + Eigen::Vector2f{ 0, 1 }, + Eigen::Vector2f{ 1, 1 } +} { +} + +class render_elements { +public: + render_elements() = default; + ~render_elements(); + + void create_resources(); + void load_mirage_pipelines(); + + // 开始新一帧的渲染 + void begin_frame(); + + // 结束当前帧并提交所有批次 + void end_frame(); + + // 设置当前渲染状态 + void set_pipeline(sg_pipeline pipeline); + void set_texture(sg_image image); + void set_projection_matrix(const Eigen::Matrix4f& in_matrix) { projection_matrix = in_matrix; } + + // 添加矩形(自动加入当前批次) + void make_rect(const Eigen::Vector2f& in_pos, + const Eigen::Vector2f& in_size, + const rect_color& in_color, + const mirage_vertex_param_t& in_param_a = {}, + const mirage_vertex_param_t& in_param_b = {}, + const mirage_vertex_param_t& in_param_c = {}, + const rect_uv& in_uv = {}, + float in_rotation_radians = 0.0f, + const Eigen::Vector2f& in_pivot = Eigen::Vector2f(1.0f, 1.0f), + const Eigen::Vector2f& in_scale = Eigen::Vector2f(0.5f, 0.5f)); + + // 添加圆角矩形 + void make_rounded_rect(const Eigen::Vector2f& in_pos, + const Eigen::Vector2f& in_size, + const rect_color& in_color, + const rect_uv& in_uv = {}, + const rect_round& in_round = {}, + float in_rotation_radians = 0.0f, + const Eigen::Vector2f& in_pivot = Eigen::Vector2f(1.0f, 1.0f), + const Eigen::Vector2f& in_scale = Eigen::Vector2f(0.5f, 0.5f)); + +private: + // 根据顶点和索引数据创建一个矩形 + void add_rect_to_batch(const Eigen::Vector2f& in_pos, + const Eigen::Vector2f& in_size, + const rect_color& in_color, + const mirage_vertex_param_t& in_param_a, + const mirage_vertex_param_t& in_param_b, + const mirage_vertex_param_t& in_param_c, + const rect_uv& in_uv, + float in_rotation_radians, + const Eigen::Vector2f& in_pivot, + const Eigen::Vector2f& in_scale); + + // 确保当前批次与给定的渲染状态兼容 + void ensure_batch_compatibility(const batch_key& key); + + // 将当前批次数据上传到GPU + void flush_batches(); + + // 创建或调整缓冲区大小 + void ensure_buffer_capacity(uint32_t vertex_count, uint32_t index_count); + + // 当前渲染状态 + batch_key current_key{}; + + // 当前批次索引 + int32_t current_batch_index = -1; + + // 所有待渲染的批次 + std::vector batches; + + // 顶点和索引数据 + std::vector vertices; + std::vector indices; + + // GPU缓冲区 + sg_buffer vertex_buffer{}; + sg_buffer index_buffer{}; + + // 缓冲区容量追踪 + uint32_t vertex_buffer_capacity = 0; + uint32_t index_buffer_capacity = 0; + + // 统计信息 + uint32_t draw_call_count = 0; + uint32_t total_triangles = 0; + + Eigen::Matrix4f projection_matrix; + + sg_pipeline rounded_rect_pipeline{}; +}; diff --git a/src/core/android/android_render_window.cpp b/src/core/window/android/android_render_window.cpp similarity index 66% rename from src/core/android/android_render_window.cpp rename to src/core/window/android/android_render_window.cpp index 8d8bf90..9cd5e8e 100644 --- a/src/core/android/android_render_window.cpp +++ b/src/core/window/android/android_render_window.cpp @@ -1,7 +1,7 @@ // // Created by Administrator on 25-3-1. // -#include "core/render_window.h" +#include "core/window/render_window.h" #include diff --git a/src/core/ios/ios_render_window.cpp b/src/core/window/ios/ios_render_window.cpp similarity index 80% rename from src/core/ios/ios_render_window.cpp rename to src/core/window/ios/ios_render_window.cpp index 20e3b8e..df3b412 100644 --- a/src/core/ios/ios_render_window.cpp +++ b/src/core/window/ios/ios_render_window.cpp @@ -1,7 +1,7 @@ // // Created by Administrator on 25-3-1. // -#include "core/render_window.h" +#include "core/window/render_window.h" #include diff --git a/src/core/linux/linux_render_window.cpp b/src/core/window/linux/linux_render_window.cpp similarity index 80% rename from src/core/linux/linux_render_window.cpp rename to src/core/window/linux/linux_render_window.cpp index d57d280..1d3edda 100644 --- a/src/core/linux/linux_render_window.cpp +++ b/src/core/window/linux/linux_render_window.cpp @@ -1,7 +1,7 @@ // // Created by Administrator on 25-3-1. // -#include "core/render_window.h" +#include "core/window/render_window.h" #include diff --git a/src/core/mac/mac_render_window.mm b/src/core/window/mac/mac_render_window.mm similarity index 80% rename from src/core/mac/mac_render_window.mm rename to src/core/window/mac/mac_render_window.mm index bfe9ad7..cfb3b97 100644 --- a/src/core/mac/mac_render_window.mm +++ b/src/core/window/mac/mac_render_window.mm @@ -1,7 +1,7 @@ // // Created by Administrator on 25-3-1. // -#include "core/render_window.h" +#include "core/window/render_window.h" #include diff --git a/src/core/render_window.cpp b/src/core/window/render_window.cpp similarity index 100% rename from src/core/render_window.cpp rename to src/core/window/render_window.cpp diff --git a/src/core/render_window.h b/src/core/window/render_window.h similarity index 100% rename from src/core/render_window.h rename to src/core/window/render_window.h diff --git a/src/core/window/windows/pixel_format_convert.h b/src/core/window/windows/pixel_format_convert.h new file mode 100644 index 0000000..76d37dc --- /dev/null +++ b/src/core/window/windows/pixel_format_convert.h @@ -0,0 +1,74 @@ +#pragma once +#include "sokol/sokol_gfx.h" +#include + +inline DXGI_FORMAT sg_pixel_format_to_dxgi(sg_pixel_format fmt) { + switch (fmt) { + case SG_PIXELFORMAT_R8: return DXGI_FORMAT_R8_UNORM; + case SG_PIXELFORMAT_R8SN: return DXGI_FORMAT_R8_SNORM; + case SG_PIXELFORMAT_R8UI: return DXGI_FORMAT_R8_UINT; + case SG_PIXELFORMAT_R8SI: return DXGI_FORMAT_R8_SINT; + case SG_PIXELFORMAT_R16: return DXGI_FORMAT_R16_UNORM; + case SG_PIXELFORMAT_R16SN: return DXGI_FORMAT_R16_SNORM; + case SG_PIXELFORMAT_R16UI: return DXGI_FORMAT_R16_UINT; + case SG_PIXELFORMAT_R16SI: return DXGI_FORMAT_R16_SINT; + case SG_PIXELFORMAT_R16F: return DXGI_FORMAT_R16_FLOAT; + case SG_PIXELFORMAT_RG8: return DXGI_FORMAT_R8G8_UNORM; + case SG_PIXELFORMAT_RG8SN: return DXGI_FORMAT_R8G8_SNORM; + case SG_PIXELFORMAT_RG8UI: return DXGI_FORMAT_R8G8_UINT; + case SG_PIXELFORMAT_RG8SI: return DXGI_FORMAT_R8G8_SINT; + case SG_PIXELFORMAT_R32UI: return DXGI_FORMAT_R32_UINT; + case SG_PIXELFORMAT_R32SI: return DXGI_FORMAT_R32_SINT; + case SG_PIXELFORMAT_R32F: return DXGI_FORMAT_R32_FLOAT; + case SG_PIXELFORMAT_RG16: return DXGI_FORMAT_R16G16_UNORM; + case SG_PIXELFORMAT_RG16SN: return DXGI_FORMAT_R16G16_SNORM; + case SG_PIXELFORMAT_RG16UI: return DXGI_FORMAT_R16G16_UINT; + case SG_PIXELFORMAT_RG16SI: return DXGI_FORMAT_R16G16_SINT; + case SG_PIXELFORMAT_RG16F: return DXGI_FORMAT_R16G16_FLOAT; + case SG_PIXELFORMAT_RGBA8: return DXGI_FORMAT_R8G8B8A8_UNORM; + case SG_PIXELFORMAT_SRGB8A8: return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + case SG_PIXELFORMAT_RGBA8SN: return DXGI_FORMAT_R8G8B8A8_SNORM; + case SG_PIXELFORMAT_RGBA8UI: return DXGI_FORMAT_R8G8B8A8_UINT; + case SG_PIXELFORMAT_RGBA8SI: return DXGI_FORMAT_R8G8B8A8_SINT; + case SG_PIXELFORMAT_BGRA8: return DXGI_FORMAT_B8G8R8A8_UNORM; + case SG_PIXELFORMAT_RGB10A2: return DXGI_FORMAT_R10G10B10A2_UNORM; + case SG_PIXELFORMAT_RG11B10F: return DXGI_FORMAT_R11G11B10_FLOAT; + case SG_PIXELFORMAT_RGB9E5: return DXGI_FORMAT_R9G9B9E5_SHAREDEXP; + case SG_PIXELFORMAT_RG32UI: return DXGI_FORMAT_R32G32_UINT; + case SG_PIXELFORMAT_RG32SI: return DXGI_FORMAT_R32G32_SINT; + case SG_PIXELFORMAT_RG32F: return DXGI_FORMAT_R32G32_FLOAT; + case SG_PIXELFORMAT_RGBA16: return DXGI_FORMAT_R16G16B16A16_UNORM; + case SG_PIXELFORMAT_RGBA16SN: return DXGI_FORMAT_R16G16B16A16_SNORM; + case SG_PIXELFORMAT_RGBA16UI: return DXGI_FORMAT_R16G16B16A16_UINT; + case SG_PIXELFORMAT_RGBA16SI: return DXGI_FORMAT_R16G16B16A16_SINT; + case SG_PIXELFORMAT_RGBA16F: return DXGI_FORMAT_R16G16B16A16_FLOAT; + case SG_PIXELFORMAT_RGBA32UI: return DXGI_FORMAT_R32G32B32A32_UINT; + case SG_PIXELFORMAT_RGBA32SI: return DXGI_FORMAT_R32G32B32A32_SINT; + case SG_PIXELFORMAT_RGBA32F: return DXGI_FORMAT_R32G32B32A32_FLOAT; + case SG_PIXELFORMAT_DEPTH: return DXGI_FORMAT_R32_TYPELESS; + case SG_PIXELFORMAT_DEPTH_STENCIL: return DXGI_FORMAT_R24G8_TYPELESS; + case SG_PIXELFORMAT_BC1_RGBA: return DXGI_FORMAT_BC1_UNORM; + case SG_PIXELFORMAT_BC2_RGBA: return DXGI_FORMAT_BC2_UNORM; + case SG_PIXELFORMAT_BC3_RGBA: return DXGI_FORMAT_BC3_UNORM; + case SG_PIXELFORMAT_BC3_SRGBA: return DXGI_FORMAT_BC3_UNORM_SRGB; + case SG_PIXELFORMAT_BC4_R: return DXGI_FORMAT_BC4_UNORM; + case SG_PIXELFORMAT_BC4_RSN: return DXGI_FORMAT_BC4_SNORM; + case SG_PIXELFORMAT_BC5_RG: return DXGI_FORMAT_BC5_UNORM; + case SG_PIXELFORMAT_BC5_RGSN: return DXGI_FORMAT_BC5_SNORM; + case SG_PIXELFORMAT_BC6H_RGBF: return DXGI_FORMAT_BC6H_SF16; + case SG_PIXELFORMAT_BC6H_RGBUF: return DXGI_FORMAT_BC6H_UF16; + case SG_PIXELFORMAT_BC7_RGBA: return DXGI_FORMAT_BC7_UNORM; + case SG_PIXELFORMAT_BC7_SRGBA: return DXGI_FORMAT_BC7_UNORM_SRGB; + default: return DXGI_FORMAT_UNKNOWN; + }; +} + +inline DXGI_FORMAT sg_pixel_format_to_dxgi_srv(sg_pixel_format fmt) { + if (fmt == SG_PIXELFORMAT_DEPTH) { + return DXGI_FORMAT_R32_FLOAT; + } + if (fmt == SG_PIXELFORMAT_DEPTH_STENCIL) { + return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + } + return sg_pixel_format_to_dxgi(fmt); +} diff --git a/src/core/windows/windows_render_context.cpp b/src/core/window/windows/windows_render_context.cpp similarity index 69% rename from src/core/windows/windows_render_context.cpp rename to src/core/window/windows/windows_render_context.cpp index 6727d19..abf3cc7 100644 --- a/src/core/windows/windows_render_context.cpp +++ b/src/core/window/windows/windows_render_context.cpp @@ -6,16 +6,12 @@ #include #include +#include "misc/angle.h" -#include "core/render_window.h" +#include "core/window/render_window.h" #include #include "windows_window_state.h" -#include "misc/scope_exit.h" -#include "shaders/test.hlsl.h" -#include "shaders/mirage_rounded_rect.hlsl.h" - -windows_mirage_render_context::~windows_mirage_render_context() { cleanup(); } bool windows_mirage_render_context::init() { try { @@ -159,6 +155,12 @@ bool windows_mirage_render_context::init() { } } +void windows_mirage_render_context::end_init() { + mirage_render_context::end_init(); + elements.create_resources(); + elements.load_mirage_pipelines(); +} + // 资源清理函数 void windows_mirage_render_context::cleanup() { mirage_render_context::cleanup(); @@ -193,20 +195,34 @@ void windows_mirage_render_context::tick(const duration_type& in_delta) { pass.swapchain = window_state->swapchain; sg_begin_pass(pass); - sg_apply_pipeline(pip); - sg_apply_viewport(0, 0, window_state->swapchain.width, window_state->swapchain.height, true); - sg_bindings bindings{}; - bindings.vertex_buffers[0] = vertex_buffer; - bindings.index_buffer = index_buffer; - sg_apply_bindings(bindings); - const auto& matrix = window->create_screen_to_dci_matrix(); + elements.set_projection_matrix(matrix); - sg_apply_uniforms(0, SG_RANGE(matrix)); + elements.begin_frame(); - sg_draw(0, 12, 2); + // draw some triangles + Eigen::Vector2f pos{ 0, 0 }; + Eigen::Vector2f pos2{ 200, 200 }; + Eigen::Vector2f size{ 200, 200 }; + elements.make_rounded_rect( + pos, + size, + rect_color({ 1, 0, 0, 1 }, { 0, 1, 1, 1 }), + {}, + rect_round({ 10, 20, 30, 40 }), + 45_deg, + { 0, 0 }, + { 1, 1 } + ); + elements.make_rounded_rect( + pos2, + size, + rect_color({ 1, 1, 0, 1 }) + ); + + elements.end_frame(); sg_end_pass(); sg_commit(); @@ -223,77 +239,9 @@ sg_environment windows_mirage_render_context::get_environment() { }; } -bool windows_mirage_render_context::setup_surface(mirage_window* in_window, bool in_hdr) { +bool windows_mirage_render_context::setup_surface(mirage_window* in_window) { auto state = std::make_unique(); - if (!state->init(device, dxgi_factory, in_window, in_hdr)) { return false; } - - shader = sg_make_shader(get_mirage_rounded_rect_shader_desc()); - - sg_pipeline_desc pipeline_desc = get_mirage_rounded_rect_pipeline_desc(shader, state->swapchain); - pip = sg_make_pipeline(pipeline_desc); - - mirage_triangle_t triangles[4]; - - // 创建顶点缓冲区(一个矩形) - std::vector vertices = { - // x, y, r, g, b, a - { { 0.f, 0.f }, { 0.f, 0.f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - // 左上 - 黄色 - { { 100.f, 0.f }, { 1.f, 0.f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - // 右上 - 蓝色 - { { 0.f, 100.f }, { 0.f, 1.f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - // 左下 - 红色 - { { 100.f, 100.f }, { 1.f, 1.f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - // 右下 - 绿色 - { { 200.f, 200.f }, { 0.f, 0.f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, - // 左上 - 黄色 - { { 300.f, 200.f }, { 1.f, 0.f }, { 1.0f, 0.0f, 1.0f, 1.0f } }, - // 右上 - 蓝色 - { { 200.f, 300.f }, { 0.f, 1.f }, { 1.0f, 0.0f, 1.0f, 1.0f } }, - // 左下 - 红色 - { { 300.f, 300.f }, { 1.f, 1.f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, - // 右下 - 绿色 - }; - for (auto& v: vertices) { - v.param_a.a = 100; - v.param_a.b = 100; - - v.param_b.a = 0; - v.param_b.b = 5; - v.param_b.c = 10; - v.param_b.d = 20; - } - - // 三角形索引不变 - triangles[0].indices[0] = 0; - triangles[0].indices[1] = 1; - triangles[0].indices[2] = 2; - triangles[1].indices[0] = 1; - triangles[1].indices[1] = 3; - triangles[1].indices[2] = 2; - - triangles[2].indices[0] = 4; - triangles[2].indices[1] = 5; - triangles[2].indices[2] = 6; - triangles[3].indices[0] = 5; - triangles[3].indices[1] = 7; - triangles[3].indices[2] = 6; - - std::span vertex_span{ vertices.data(), vertices.size() }; - sg_buffer_desc vertex_buffer_desc{ - .size = vertex_span.size_bytes() * 2, - .type = SG_BUFFERTYPE_VERTEXBUFFER, - .usage = SG_USAGE_DYNAMIC, - }; - vertex_buffer = sg_make_buffer(vertex_buffer_desc); - std::span vertex_span2{ vertices.data(), vertices.size() }; - sg_update_buffer(vertex_buffer, sg_range{ vertex_span2.data(), vertex_span2.size_bytes() }); - - index_buffer = sg_make_buffer(sg_buffer_desc{ - .type = SG_BUFFERTYPE_INDEXBUFFER, - .usage = SG_USAGE_IMMUTABLE, - .data = SG_RANGE(triangles), - }); + if (!state->init(device, dxgi_factory, in_window)) { return false; } in_window->state = std::move(state); return true; diff --git a/src/core/windows/windows_render_context.h b/src/core/window/windows/windows_render_context.h similarity index 69% rename from src/core/windows/windows_render_context.h rename to src/core/window/windows/windows_render_context.h index 0144b65..01a48b4 100644 --- a/src/core/windows/windows_render_context.h +++ b/src/core/window/windows/windows_render_context.h @@ -1,19 +1,22 @@ #pragma once #include +#include +#include "sokol/sokol_header.h" #include "core/render_context.h" +#include "core/render_elements.h" class windows_mirage_render_context : public mirage_render_context { public: windows_mirage_render_context() = default; - virtual ~windows_mirage_render_context() override; bool init() override; + virtual void end_init() override; void cleanup() override; virtual void tick(const duration_type& in_delta) override; sg_environment get_environment() override; - bool setup_surface(mirage_window* in_window, bool in_hdr) override; + bool setup_surface(mirage_window* in_window) override; private: ID3D11Device* device{}; ID3D11DeviceContext* device_context{}; @@ -21,8 +24,5 @@ private: IDXGIFactory* dxgi_factory{}; D3D_FEATURE_LEVEL feature_level; - sg_shader shader{}; - sg_pipeline pip{}; - sg_buffer vertex_buffer{}; - sg_buffer index_buffer{}; + render_elements elements; }; diff --git a/src/core/windows/windows_render_window.cpp b/src/core/window/windows/windows_render_window.cpp similarity index 99% rename from src/core/windows/windows_render_window.cpp rename to src/core/window/windows/windows_render_window.cpp index 87442d5..9914e60 100644 --- a/src/core/windows/windows_render_window.cpp +++ b/src/core/window/windows/windows_render_window.cpp @@ -3,7 +3,7 @@ // #include -#include "core/render_window.h" +#include "../render_window.h" #include #define WINDOW_HANDLE static_cast(window_handle) diff --git a/src/core/windows/windows_window_state.cpp b/src/core/window/windows/windows_window_state.cpp similarity index 86% rename from src/core/windows/windows_window_state.cpp rename to src/core/window/windows/windows_window_state.cpp index 1ef4ae7..122ae22 100644 --- a/src/core/windows/windows_window_state.cpp +++ b/src/core/window/windows/windows_window_state.cpp @@ -1,18 +1,22 @@ #include "windows_window_state.h" - #include +#include "pixel_format_convert.h" #include "misc/scope_exit.h" -bool windows_window_state::init(ID3D11Device* in_device, IDXGIFactory* in_factory, mirage_window* in_window, - bool in_hdr) { +bool windows_window_state::init(ID3D11Device* in_device, IDXGIFactory* in_factory, mirage_window* in_window) { dx_device = in_device; dxgi_factory = in_factory; const auto size = in_window->get_window_frame_size(); const auto window_handle = in_window->get_window_handle(); - const auto format = in_hdr ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_R8G8B8A8_UNORM; +#ifdef MIRAGE_USE_HDR + constexpr auto sg_format = MIRAGE_HDR_FORMAT; +#else + constexpr auto sg_format = MIRAGE_PIXEL_FORMAT; +#endif + const auto format = sg_pixel_format_to_dxgi_srv(sg_format); // 创建D3D11渲染目标视图 DXGI_SWAP_CHAIN_DESC swap_chain_desc = { @@ -62,10 +66,19 @@ bool windows_window_state::init(ID3D11Device* in_device, IDXGIFactory* in_factor return false; } +// #ifdef MIRAGE_USE_HDR +// // 设置HDR元数据 +// DXGI_HDR_METADATA_HDR10 metadata = {}; +// metadata.MaxMasteringLuminance = 1000 * 10000; // 1000尼特 +// metadata.MinMasteringLuminance = 0.001 * 10000; // 0.001尼特 +// // ...设置其他元数据 +// dx_swap_chain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_HDR10, sizeof(metadata), &metadata); +// #endif + swapchain.d3d11.render_view = render_target_view; swapchain.width = static_cast(size.x()); swapchain.height = static_cast(size.y()); - swapchain.color_format = in_hdr ? SG_PIXELFORMAT_RGBA16F : SG_PIXELFORMAT_RGBA8; + swapchain.color_format = sg_format; swapchain.depth_format = SG_PIXELFORMAT_NONE; swapchain.sample_count = 1; swapchain.d3d11.resolve_view = nullptr; diff --git a/src/core/windows/windows_window_state.h b/src/core/window/windows/windows_window_state.h similarity index 85% rename from src/core/windows/windows_window_state.h rename to src/core/window/windows/windows_window_state.h index 67b1f82..3138d88 100644 --- a/src/core/windows/windows_window_state.h +++ b/src/core/window/windows/windows_window_state.h @@ -1,13 +1,14 @@ #pragma once -#include "core/render_window.h" +#include "core/window/render_window.h" #include +#include struct windows_window_state final : mirage_window_state { ID3D11RenderTargetView* get_dx_render_target_view() const { return (ID3D11RenderTargetView*)swapchain.d3d11.render_view; } - bool init(ID3D11Device* in_device, IDXGIFactory* in_factory, mirage_window* in_window, bool in_hdr); + bool init(ID3D11Device* in_device, IDXGIFactory* in_factory, mirage_window* in_window); virtual void clear() override; diff --git a/src/mirage.cpp b/src/mirage.cpp index 1b4809c..4a993c8 100644 --- a/src/mirage.cpp +++ b/src/mirage.cpp @@ -1,15 +1,13 @@ -#include "mirage.h" - #define SOKOL_IMPL -#include "sokol/sokol_gfx.h" + +#include "mirage.h" #include #include -#include "core/render_window.h" +#include "core/window/render_window.h" #include "misc/mirage_scoped_duration_timer.h" - void mirage_log(const char* tag, uint32_t log_level, uint32_t log_item_id, const char* message_or_null, uint32_t line_nr, const char* filename_or_null, void* user_data) { if (log_level == 0) // painc @@ -38,6 +36,7 @@ void mirage_app::init() { .environment = render_context->get_environment(), }; sg_setup(desc); + render_context->end_init(); } // 初始化用时 std::cout << "mirage: " << "Initialization took " << std::chrono::duration_cast(duration).count() << "ms" << std::endl; @@ -50,7 +49,9 @@ void mirage_app::run() { render_context->tick(delta_time); last_time = get_current_time(); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + // std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::this_thread::yield(); } + render_context->cleanup(); delete render_context; } diff --git a/src/misc/angle.h b/src/misc/angle.h new file mode 100644 index 0000000..c0f3415 --- /dev/null +++ b/src/misc/angle.h @@ -0,0 +1,9 @@ +#pragma once + +consteval float operator"" _deg(const long double in_degree) { + return static_cast(in_degree * 3.1415926f / 180.0f); +} + +consteval float operator"" _deg(const unsigned long long in_degree) { + return in_degree * 3.1415926f / 180.0f; +} diff --git a/src/misc/color.cpp b/src/misc/color.cpp new file mode 100644 index 0000000..c5af376 --- /dev/null +++ b/src/misc/color.cpp @@ -0,0 +1,5 @@ +#include "color.h" + +const linear_color linear_color::white = { 1.0f, 1.0f, 1.0f, 1.0f }; +const linear_color linear_color::black = { 0.0f, 0.0f, 0.0f, 1.0f }; +const linear_color linear_color::transparent = { 0.0f, 0.0f, 0.0f, 1.0f }; diff --git a/src/misc/color.h b/src/misc/color.h new file mode 100644 index 0000000..194a41e --- /dev/null +++ b/src/misc/color.h @@ -0,0 +1,58 @@ +#pragma once +#include + +class linear_color { +public: + linear_color() : r(1), g(1), b(1), a(1) { + } + + linear_color(float in_r, float in_g, float in_b, float in_a = 1.0f) : r(in_r), g(in_g), b(in_b), a(in_a) { + } + + static linear_color from_srgb(float in_r, float in_g, float in_b, float in_a = 1.0f) { + return linear_color( + in_r <= 0.04045f ? in_r / 12.92f : std::pow((in_r + 0.055f) / 1.055f, 2.4f), + in_g <= 0.04045f ? in_g / 12.92f : std::pow((in_g + 0.055f) / 1.055f, 2.4f), + in_b <= 0.04045f ? in_b / 12.92f : std::pow((in_b + 0.055f) / 1.055f, 2.4f), + in_a + ); + } + + static linear_color from_srgb(const linear_color& in_color) { + return from_srgb(in_color.r, in_color.g, in_color.b, in_color.a); + } + + linear_color& operator+=(const linear_color& in_color) { + r += in_color.r; + g += in_color.g; + b += in_color.b; + a += in_color.a; + return *this; + } + + linear_color& operator-=(const linear_color& in_color) { + r -= in_color.r; + g -= in_color.g; + b -= in_color.b; + a -= in_color.a; + return *this; + } + + linear_color operator+(const linear_color& in_color) const { + return { r + in_color.r, g + in_color.g, b + in_color.b, a + in_color.a }; + } + + linear_color operator-(const linear_color& in_color) const { + return { r - in_color.r, g - in_color.g, b - in_color.b, a - in_color.a }; + } + + bool operator==(const linear_color& in_color) const { + return r == in_color.r && g == in_color.g && b == in_color.b && a == in_color.a; + } + + float r, g, b, a; + + static const linear_color white; + static const linear_color black; + static const linear_color transparent; +}; diff --git a/src/misc/mirage_type.h b/src/misc/mirage_type.h index 2e6a5a8..a138981 100644 --- a/src/misc/mirage_type.h +++ b/src/misc/mirage_type.h @@ -2,43 +2,150 @@ #include #include -using time_type = decltype(std::chrono::high_resolution_clock::now()); +#include "color.h" + +using time_type = decltype(std::chrono::high_resolution_clock::now()); using duration_type = decltype(std::chrono::high_resolution_clock::now() - std::chrono::high_resolution_clock::now()); -inline time_type get_current_time() { - return std::chrono::high_resolution_clock::now(); -} +inline time_type get_current_time() { return std::chrono::high_resolution_clock::now(); } -// struct VSInput { -// float2 position : POSITION; -// float2 uv : TEXCOORD0; -// float4 color : COLOR0; -// float4 param_a : TEXCOORD1; -// float4 param_b : TEXCOORD2; -// float4 param_c : TEXCOORD3; -// }; -struct mirage_vertex_param_t{ - union { - float a; - float x; - }; - union { - float b; - float y; - }; - union { - float c; - float z; - }; - union { - float d; - float w; - }; +// 左上,右上,左下,右下 +template +struct rect_quad : std::array { + // 默认构造函数由具体类型特化提供 + + rect_quad() : std::array() { + } + + // 单值构造 + rect_quad(const T& value) : std::array{ value, value, value, value } { + } + + // 左右构造 + rect_quad(const T& left, const T& right) : std::array{ left, right, left, right } { + } + + // 完整构造 + rect_quad(const T& left_top, const T& right_top, + const T& left_bottom, const T& right_bottom) : std::array{ + left_top, + right_top, + left_bottom, + right_bottom + } { + } }; + +struct mirage_vertex_param_t { + // 默认构造函数 + mirage_vertex_param_t() = default; + + // 通用构造函数 - 处理任何支持[]运算符的容器类型 + template, mirage_vertex_param_t> && + !std::is_arithmetic_v> + >, + typename = decltype(std::declval()[0])> // 检查是否支持索引访问 + mirage_vertex_param_t(const Container& container) { + try { + x = static_cast(container[0]); + + // 对于各种不同类型的容器,尝试安全地获取剩余元素 + // 固定大小容器 (std::array, rect_quad 等) + if constexpr (has_tuple_size::value) { + constexpr size_t N = std::tuple_size>::value; + y = (N > 1) ? static_cast(container[1]) : 0.0f; + z = (N > 2) ? static_cast(container[2]) : 0.0f; + w = (N > 3) ? static_cast(container[3]) : 0.0f; + } + // Eigen::Vector + else if constexpr (is_eigen_vector::value) { + constexpr int N = Container::RowsAtCompileTime; + y = (N > 1) ? static_cast(container[1]) : 0.0f; + z = (N > 2) ? static_cast(container[2]) : 0.0f; + w = (N > 3) ? static_cast(container[3]) : 0.0f; + } + // 动态大小容器 (std::vector 等) + else if constexpr (has_size_method::value) { + y = (container.size() > 1) ? static_cast(container[1]) : 0.0f; + z = (container.size() > 2) ? static_cast(container[2]) : 0.0f; + w = (container.size() > 3) ? static_cast(container[3]) : 0.0f; + } + // 其他情况 - 尝试访问但可能会抛出异常 + else { + try { y = static_cast(container[1]); } catch(...) { y = 0.0f; } + try { z = static_cast(container[2]); } catch(...) { z = 0.0f; } + try { w = static_cast(container[3]); } catch(...) { w = 0.0f; } + } + } catch(...) { + // 如果第一个元素访问失败,设置所有值为0 + x = y = z = w = 0.0f; + } + } + + // 处理标量类型的构造函数 + template>>> + mirage_vertex_param_t(T val) : x(val), y(0), z(0), w(0) {} + + // 处理2个标量的构造函数 + template + mirage_vertex_param_t(T x_val, T y_val) : x(x_val), y(y_val), z(0), w(0) {} + + // 处理3个标量的构造函数 + template + mirage_vertex_param_t(T x_val, T y_val, T z_val) : x(x_val), y(y_val), z(z_val), w(0) {} + + // 处理4个标量的构造函数 + template + mirage_vertex_param_t(T x_val, T y_val, T z_val, T w_val) : + x(x_val), y(y_val), z(z_val), w(w_val) {} + + // 处理两个容器的构造函数 + template()[0]), + typename = decltype(std::declval()[0])> + mirage_vertex_param_t(const A& a, const B& b) : + x(static_cast(a[0])), + y(static_cast(a[1])), + z(static_cast(b[0])), + w(static_cast(b[1])) {} + + // 辅助类型特征检测 + template + struct has_tuple_size : std::false_type {}; + + template + struct has_tuple_size>::value)>> + : std::true_type {}; + + template + struct has_size_method : std::false_type {}; + + template + struct has_size_method().size())>> + : std::true_type {}; + + template + struct is_eigen_vector : std::false_type {}; + + template + struct is_eigen_vector> + : std::true_type {}; + + // 数据成员 + union { float a; float x; }; + union { float b; float y; }; + union { float c; float z; }; + union { float d; float w; }; +}; + + struct mirage_vertex_t { - Eigen::Vector2f position; - Eigen::Vector2f uv; - Eigen::Vector4f color; + Eigen::Vector2f position; + Eigen::Vector2f uv; + linear_color color; mirage_vertex_param_t param_a; mirage_vertex_param_t param_b; mirage_vertex_param_t param_c; diff --git a/src/sokol/sokol_header.h b/src/sokol/sokol_header.h new file mode 100644 index 0000000..5f452e7 --- /dev/null +++ b/src/sokol/sokol_header.h @@ -0,0 +1,3 @@ +#pragma once + +#include "sokol/sokol_gfx.h" diff --git a/tools/mirage_shdc.exe b/tools/win_mirage_shdc.exe similarity index 99% rename from tools/mirage_shdc.exe rename to tools/win_mirage_shdc.exe index 6ae8484..f98ff58 100644 Binary files a/tools/mirage_shdc.exe and b/tools/win_mirage_shdc.exe differ