整理目录

This commit is contained in:
Nanako 2025-03-16 00:39:40 +08:00
parent 4727a47616
commit f288752e38
27 changed files with 802 additions and 166 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ fips-files/deploy/
.idea/
CMakeUserPresets.json
#<fips
/tools/shader_path.txt

View File

@ -18,6 +18,16 @@ if (WIN32)
add_definitions(-DUNICODE -D_UNICODE)
endif ()
set(MIRAGE_USE_HDR OFF CACHE BOOL "Enable HDR format")
set(MIRAGE_HDR_FORMAT "SG_PIXELFORMAT_RGBA16F" CACHE STRING "Enable HDR format")
set(MIRAGE_PIXEL_FORMAT "SG_PIXELFORMAT_RGBA8" CACHE STRING "Pixel format")
if (MIRAGE_USE_HDR)
add_definitions(-DMIRAGE_USE_HDR)
endif ()
add_definitions(-DMIRAGE_HDR_FORMAT=${MIRAGE_HDR_FORMAT} -DMIRAGE_PIXEL_FORMAT=${MIRAGE_PIXEL_FORMAT})
set(MSDFGEN_USE_SKIA OFF CACHE BOOL "Use Skia for MSDFGen" FORCE)
set(MSDFGEN_USE_VCPKG OFF CACHE BOOL "Use VCPKG for MSDFGen" FORCE)
set(MSDFGEN_USE_OPENMP ON CACHE BOOL "Use OpenMP for MSDFGen" FORCE)

View File

@ -23,22 +23,19 @@ function(add_mirage_shader_directory path)
foreach(SHADER_FILE ${SHADER_FILES})
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${SHADER_FILE})
endforeach()
# 便使
set(SHADER_FILES_GLOBAL ${SHADER_FILES_GLOBAL} ${SHADER_FILES} PARENT_SCOPE)
endfunction()
set(SHADER_COMPILE_ARGS "")
set(SHADER_SHDC "")
if (WIN32)
list(APPEND SHADER_COMPILE_ARGS "--hlsl")
set(SHADER_SHDC ${MIRAGE_ROOT_DIR}/tools/mirage_shdc.exe)
set(SHADER_SHDC ${MIRAGE_ROOT_DIR}/tools/win_mirage_shdc.exe)
elseif (APPLE)
list(APPEND SHADER_COMPILE_ARGS "--metal")
set(SHADER_SHDC ${MIRAGE_ROOT_DIR}/tools/mirage_shdc)
set(SHADER_SHDC ${MIRAGE_ROOT_DIR}/tools/mac_mirage_shdc)
else()
list(APPEND SHADER_COMPILE_ARGS "--glsl")
set(SHADER_SHDC ${MIRAGE_ROOT_DIR}/tools/mirage_shdc)
set(SHADER_SHDC ${MIRAGE_ROOT_DIR}/tools/linux_mirage_shdc)
endif()
# Debug, --debug
@ -56,19 +53,6 @@ add_custom_target(compile_shaders ALL
VERBATIM
)
#
add_custom_target(force_recompile_shaders
COMMAND ${CMAKE_COMMAND} -E remove -f ${SHADER_PATH_FILE}
COMMAND ${CMAKE_COMMAND} -E touch ${SHADER_PATH_FILE}
COMMAND ${Python3_EXECUTABLE} ${SHADER_COMPILE_SCRIPT}
--shdc ${SHADER_SHDC}
--shader_list ${SHADER_PATH_FILE}
${SHADER_COMPILE_ARGS}
--force
COMMENT ""
VERBATIM
)
#
function(add_shader_dependencies target)
add_dependencies(${target} compile_shaders)

View File

@ -3,7 +3,7 @@
//
#include "mirage.h"
#include "core/render_window.h"
#include "core/window/render_window.h"
int main(int argc, char* argv[]) {
mirage_app app;
@ -12,7 +12,7 @@ int main(int argc, char* argv[]) {
mirage_window window;
window.create_window(800, 600, L"Hello, World!");
window.show();
app.get_render_context()->setup_surface(&window, false);
app.get_render_context()->setup_surface(&window);
app.run();
return 0;

View File

@ -2,6 +2,12 @@ cmake_minimum_required(VERSION 3.15)
project(mirage_core LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 26)
if (MSVC)
# MSVCC++
add_compile_options(/std:c++latest)
# utf-8
add_compile_options(/utf-8)
endif ()
find_package(Freetype REQUIRED)
find_package(Eigen3 REQUIRED)

View File

@ -1,9 +1,7 @@
#pragma once
#include "sokol/sokol_gfx.h"
#include "misc/mirage_type.h"
#include <functional>
#include <map>
#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();

View File

@ -0,0 +1,274 @@
#include "render_elements.h"
#include "shaders/mirage_rounded_rect.hlsl.h"
template<typename Derived>
void compute_rect_vertices(const Eigen::MatrixBase<Derived>& in_pos,
const Eigen::MatrixBase<Derived>& in_size,
Eigen::Matrix<float, 2, 4>& 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<float> rotation(rotation_radians);
const Eigen::Matrix2f rot_matrix = rotation.toRotationMatrix();
// 计算基于原点的矩形顶点(左上角在原点)
Eigen::Matrix<float, 2, 4> 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<float, 2, 4> 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);
}

143
src/core/render_elements.h Normal file
View File

@ -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<linear_color>;
using rect_uv = rect_quad<Eigen::Vector2f>;
using rect_round = rect_quad<float>;
// 为rect_uv提供默认构造函数特化
template<>
inline rect_quad<Eigen::Vector2f>::rect_quad() : std::array<Eigen::Vector2f, 4>{
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<draw_batch> batches;
// 顶点和索引数据
std::vector<mirage_vertex_t> vertices;
std::vector<uint32_t> 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{};
};

View File

@ -1,7 +1,7 @@
//
// Created by Administrator on 25-3-1.
//
#include "core/render_window.h"
#include "core/window/render_window.h"
#include <GLFW/glfw3native.h>

View File

@ -1,7 +1,7 @@
//
// Created by Administrator on 25-3-1.
//
#include "core/render_window.h"
#include "core/window/render_window.h"
#include <GLFW/glfw3native.h>

View File

@ -1,7 +1,7 @@
//
// Created by Administrator on 25-3-1.
//
#include "core/render_window.h"
#include "core/window/render_window.h"
#include <GLFW/glfw3native.h>

View File

@ -1,7 +1,7 @@
//
// Created by Administrator on 25-3-1.
//
#include "core/render_window.h"
#include "core/window/render_window.h"
#include <GLFW/glfw3native.h>

View File

@ -0,0 +1,74 @@
#pragma once
#include "sokol/sokol_gfx.h"
#include <d3d11.h>
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);
}

View File

@ -6,16 +6,12 @@
#include <iostream>
#include <ranges>
#include "misc/angle.h"
#include "core/render_window.h"
#include "core/window/render_window.h"
#include <windows.h>
#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<windows_window_state>();
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<mirage_vertex_t> 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;

View File

@ -1,19 +1,22 @@
#pragma once
#include <d3d11.h>
#include <dxgi1_5.h>
#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;
};

View File

@ -3,7 +3,7 @@
//
#include <iostream>
#include "core/render_window.h"
#include "../render_window.h"
#include <Windows.h>
#define WINDOW_HANDLE static_cast<HWND>(window_handle)

View File

@ -1,18 +1,22 @@
#include "windows_window_state.h"
#include <iostream>
#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<int>(size.x());
swapchain.height = static_cast<int>(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;

View File

@ -1,13 +1,14 @@
#pragma once
#include "core/render_window.h"
#include "core/window/render_window.h"
#include <d3d11.h>
#include <dxgi1_5.h>
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;

View File

@ -1,15 +1,13 @@
#include "mirage.h"
#define SOKOL_IMPL
#include "sokol/sokol_gfx.h"
#include "mirage.h"
#include <iostream>
#include <thread>
#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<std::chrono::milliseconds>(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;
}

9
src/misc/angle.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
consteval float operator"" _deg(const long double in_degree) {
return static_cast<float>(in_degree * 3.1415926f / 180.0f);
}
consteval float operator"" _deg(const unsigned long long in_degree) {
return in_degree * 3.1415926f / 180.0f;
}

5
src/misc/color.cpp Normal file
View File

@ -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 };

58
src/misc/color.h Normal file
View File

@ -0,0 +1,58 @@
#pragma once
#include <complex>
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;
};

View File

@ -2,43 +2,150 @@
#include <chrono>
#include <Eigen/Eigen>
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<typename T>
struct rect_quad : std::array<T, 4> {
// 默认构造函数由具体类型特化提供
rect_quad() : std::array<T, 4>() {
}
// 单值构造
rect_quad(const T& value) : std::array<T, 4>{ value, value, value, value } {
}
// 左右构造
rect_quad(const T& left, const T& right) : std::array<T, 4>{ left, right, left, right } {
}
// 完整构造
rect_quad(const T& left_top, const T& right_top,
const T& left_bottom, const T& right_bottom) : std::array<T, 4>{
left_top,
right_top,
left_bottom,
right_bottom
} {
}
};
struct mirage_vertex_param_t {
// 默认构造函数
mirage_vertex_param_t() = default;
// 通用构造函数 - 处理任何支持[]运算符的容器类型
template<typename Container,
typename = std::enable_if_t<
!std::is_same_v<std::decay_t<Container>, mirage_vertex_param_t> &&
!std::is_arithmetic_v<std::decay_t<Container>>
>,
typename = decltype(std::declval<Container>()[0])> // 检查是否支持索引访问
mirage_vertex_param_t(const Container& container) {
try {
x = static_cast<float>(container[0]);
// 对于各种不同类型的容器,尝试安全地获取剩余元素
// 固定大小容器 (std::array, rect_quad 等)
if constexpr (has_tuple_size<Container>::value) {
constexpr size_t N = std::tuple_size<std::decay_t<Container>>::value;
y = (N > 1) ? static_cast<float>(container[1]) : 0.0f;
z = (N > 2) ? static_cast<float>(container[2]) : 0.0f;
w = (N > 3) ? static_cast<float>(container[3]) : 0.0f;
}
// Eigen::Vector
else if constexpr (is_eigen_vector<Container>::value) {
constexpr int N = Container::RowsAtCompileTime;
y = (N > 1) ? static_cast<float>(container[1]) : 0.0f;
z = (N > 2) ? static_cast<float>(container[2]) : 0.0f;
w = (N > 3) ? static_cast<float>(container[3]) : 0.0f;
}
// 动态大小容器 (std::vector 等)
else if constexpr (has_size_method<Container>::value) {
y = (container.size() > 1) ? static_cast<float>(container[1]) : 0.0f;
z = (container.size() > 2) ? static_cast<float>(container[2]) : 0.0f;
w = (container.size() > 3) ? static_cast<float>(container[3]) : 0.0f;
}
// 其他情况 - 尝试访问但可能会抛出异常
else {
try { y = static_cast<float>(container[1]); } catch(...) { y = 0.0f; }
try { z = static_cast<float>(container[2]); } catch(...) { z = 0.0f; }
try { w = static_cast<float>(container[3]); } catch(...) { w = 0.0f; }
}
} catch(...) {
// 如果第一个元素访问失败设置所有值为0
x = y = z = w = 0.0f;
}
}
// 处理标量类型的构造函数
template<typename T,
typename = std::enable_if_t<std::is_arithmetic_v<std::decay_t<T>>>>
mirage_vertex_param_t(T val) : x(val), y(0), z(0), w(0) {}
// 处理2个标量的构造函数
template<typename T>
mirage_vertex_param_t(T x_val, T y_val) : x(x_val), y(y_val), z(0), w(0) {}
// 处理3个标量的构造函数
template<typename T>
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<typename T>
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<typename A, typename B,
typename = decltype(std::declval<A>()[0]),
typename = decltype(std::declval<B>()[0])>
mirage_vertex_param_t(const A& a, const B& b) :
x(static_cast<float>(a[0])),
y(static_cast<float>(a[1])),
z(static_cast<float>(b[0])),
w(static_cast<float>(b[1])) {}
// 辅助类型特征检测
template<typename T, typename = void>
struct has_tuple_size : std::false_type {};
template<typename T>
struct has_tuple_size<T, std::void_t<decltype(std::tuple_size<std::decay_t<T>>::value)>>
: std::true_type {};
template<typename T, typename = void>
struct has_size_method : std::false_type {};
template<typename T>
struct has_size_method<T, std::void_t<decltype(std::declval<T>().size())>>
: std::true_type {};
template<typename T, typename = void>
struct is_eigen_vector : std::false_type {};
template<typename T>
struct is_eigen_vector<T, std::void_t<decltype(T::RowsAtCompileTime)>>
: 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;

3
src/sokol/sokol_header.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#include "sokol/sokol_gfx.h"