图片绘制
This commit is contained in:
parent
2c5ea1e7e9
commit
dc896d51f3
@ -9,7 +9,8 @@
|
||||
#include "pixel.h"
|
||||
#include "misc/mapped_file/mapped_file.h"
|
||||
#include "stb_image_loader.h"
|
||||
#include "render/render_image.h"
|
||||
#include "render/texture2d.h"
|
||||
#include "widget/leaf_widget/mimage.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
mirage_app::get().init();
|
||||
@ -17,17 +18,21 @@ int main(int argc, char* argv[]) {
|
||||
auto file = mapped_file::create();
|
||||
file->map_file(L"Z:/Root/Local/NanakoDisk/涩图/可爱偷猴计划/东风谷早苗/57092520_p1.jpg");
|
||||
|
||||
stb_image_loader image;
|
||||
image.init(file->get_data(), file->get_size());
|
||||
const auto& heap = image.load();
|
||||
auto i = std::make_shared<texture2d>();
|
||||
|
||||
render_image i;
|
||||
i.create(heap->data, { heap->info.width, heap->info.height }, heap->info.get_pixel_format());
|
||||
{
|
||||
stb_image_loader image_loader;
|
||||
image_loader.init(file->get_data(), file->get_size());
|
||||
const auto& heap = image_loader.load();
|
||||
|
||||
i->create(heap->data, { heap->info.width, heap->info.height }, heap->info.get_pixel_format());
|
||||
}
|
||||
|
||||
auto image = std::make_shared<mimage>();
|
||||
image->set_image(i);
|
||||
|
||||
const auto& window = mwindow::create({ 800, 600 }, L"Hello, World!");
|
||||
window->set_content(
|
||||
std::make_shared<mbutton>()
|
||||
);
|
||||
window->set_content(image);
|
||||
|
||||
mirage_app::get().run();
|
||||
return 0;
|
||||
|
@ -88,6 +88,7 @@ void mirage_app::run() {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
running = false;
|
||||
texture_sampler_builder::clear();
|
||||
render_context->cleanup();
|
||||
delete render_context;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "render_elements.h"
|
||||
#include "shaders/mirage_rounded_rect.hlsl.h"
|
||||
#include "shaders/mirage_image.hlsl.h"
|
||||
|
||||
template<typename Derived>
|
||||
void compute_rect_vertices(const Eigen::MatrixBase<Derived>& in_pos,
|
||||
@ -62,6 +63,12 @@ void render_elements::set_texture(sg_image image) {
|
||||
ensure_batch_compatibility(new_key);
|
||||
}
|
||||
|
||||
void render_elements::set_sampler(sg_sampler sampler) {
|
||||
batch_key new_key = current_key_;
|
||||
new_key.sampler = sampler;
|
||||
ensure_batch_compatibility(new_key);
|
||||
}
|
||||
|
||||
Eigen::Matrix4f render_elements::create_projection_matrix(const Eigen::Vector2i& in_size) {
|
||||
Eigen::Matrix4f projection_matrix = Eigen::Matrix4f::Identity();
|
||||
|
||||
@ -120,8 +127,8 @@ void render_elements::add_rect_to_batch(
|
||||
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) {
|
||||
const Eigen::Vector2f& in_scale,
|
||||
const Eigen::Vector2f& in_pivot) {
|
||||
// 确保有活跃的批次
|
||||
if (current_batch_index_ < 0) {
|
||||
set_pipeline(sg_pipeline{}); // 使用默认管线
|
||||
@ -130,7 +137,7 @@ void render_elements::add_rect_to_batch(
|
||||
|
||||
// 计算顶点位置
|
||||
Eigen::Matrix<float, 2, 4> positions;
|
||||
compute_rect_vertices(in_pos, in_size, positions, in_rotation_radians, in_pivot, in_scale);
|
||||
compute_rect_vertices(in_pos, in_size, positions, in_rotation_radians, in_scale, in_pivot);
|
||||
|
||||
// 记录起始顶点索引
|
||||
uint32_t base_index = vertices_.size();
|
||||
@ -186,8 +193,8 @@ void render_elements::make_rect(
|
||||
in_param_c,
|
||||
in_uv,
|
||||
in_rotation_radians,
|
||||
in_pivot,
|
||||
in_scale);
|
||||
in_scale,
|
||||
in_pivot);
|
||||
}
|
||||
|
||||
void render_elements::make_rounded_rect(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size,
|
||||
@ -196,7 +203,43 @@ void render_elements::make_rounded_rect(const Eigen::Vector2f& in_pos, const Eig
|
||||
set_pipeline(rounded_rect_pipeline_);
|
||||
const mirage_vertex_param_t param_a{ in_size };
|
||||
const mirage_vertex_param_t param_b{ in_round };
|
||||
make_rect(in_pos, in_size, in_color, in_geometry, param_a, param_b, {}, in_uv, in_rotation_radians, in_scale, in_pivot);
|
||||
make_rect(in_pos, in_size, in_color, in_geometry, param_a, param_b, {}, in_uv, in_rotation_radians, in_pivot, in_scale);
|
||||
}
|
||||
|
||||
void render_elements::make_image(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size,
|
||||
const geometry_t& in_geometry, const sg_image& in_image, sampler_type in_sampler_type,
|
||||
const linear_color& in_color, const rect_uv& in_uv, float in_rotation_radians, const Eigen::Vector2f& in_pivot,
|
||||
const Eigen::Vector2f& in_scale) {
|
||||
const auto& sampler = texture_sampler_builder::get_sampler(in_sampler_type);
|
||||
make_image(in_pos,
|
||||
in_size,
|
||||
in_geometry,
|
||||
in_image,
|
||||
sampler,
|
||||
in_color,
|
||||
in_uv,
|
||||
in_rotation_radians,
|
||||
in_pivot,
|
||||
in_scale);
|
||||
}
|
||||
|
||||
void render_elements::make_image(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size,
|
||||
const geometry_t& in_geometry, const sg_image& in_image, std::shared_ptr<texture_sampler> in_sampler,
|
||||
const linear_color& in_color, const rect_uv& in_uv, float in_rotation_radians, const Eigen::Vector2f& in_pivot,
|
||||
const Eigen::Vector2f& in_scale) {
|
||||
if (!in_sampler) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建完整的批次键
|
||||
batch_key new_key;
|
||||
new_key.pipeline = image_pipeline_;
|
||||
new_key.image = in_image;
|
||||
new_key.sampler = *in_sampler;
|
||||
|
||||
ensure_batch_compatibility(new_key);
|
||||
|
||||
make_rect(in_pos, in_size, { in_color }, in_geometry, {}, {}, {}, in_uv, in_rotation_radians, in_pivot, in_scale);
|
||||
}
|
||||
|
||||
// 确保缓冲区容量
|
||||
@ -247,6 +290,7 @@ void render_elements::flush_batches() {
|
||||
for (const auto& batch: batches_) {
|
||||
// 设置纹理
|
||||
bind.images[0] = batch.key.image;
|
||||
bind.samplers[0] = batch.key.sampler;
|
||||
|
||||
// 绑定管线
|
||||
sg_apply_pipeline(batch.key.pipeline);
|
||||
@ -300,8 +344,10 @@ void render_elements::load_mirage_pipelines() {
|
||||
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);
|
||||
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);
|
||||
|
||||
auto image_shader = sg_make_shader(get_mirage_image_shader_desc());
|
||||
auto image_pipeline_desc = get_mirage_image_pipeline_desc(image_shader, format, 1);
|
||||
image_pipeline_ = sg_make_pipeline(image_pipeline_desc);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "geometry/layout_transform.h"
|
||||
#include "sokol_gfx.h"
|
||||
#include "color.h"
|
||||
#include "texture_sampler.h"
|
||||
#include "misc/mirage_type.h"
|
||||
|
||||
/**
|
||||
@ -34,6 +35,10 @@ struct batch_key {
|
||||
|
||||
/** 使用的纹理 */
|
||||
sg_image image{};
|
||||
|
||||
/** 使用的采样器 */
|
||||
sg_sampler sampler{};
|
||||
|
||||
// 可选:添加其他影响状态的元素,如着色器、混合模式等
|
||||
|
||||
/**
|
||||
@ -43,7 +48,8 @@ struct batch_key {
|
||||
*/
|
||||
bool operator==(const batch_key& other) const {
|
||||
return pipeline.id == other.pipeline.id &&
|
||||
image.id == other.image.id;
|
||||
image.id == other.image.id &&
|
||||
sampler.id == other.sampler.id;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,7 +60,9 @@ struct batch_key {
|
||||
bool operator<(const batch_key& other) const {
|
||||
if (pipeline.id != other.pipeline.id)
|
||||
return pipeline.id < other.pipeline.id;
|
||||
if (image.id != other.image.id)
|
||||
return image.id < other.image.id;
|
||||
return sampler.id < other.sampler.id; // 缺少这一行
|
||||
}
|
||||
};
|
||||
|
||||
@ -181,6 +189,12 @@ public:
|
||||
*/
|
||||
void set_texture(sg_image image);
|
||||
|
||||
/**
|
||||
* @brief 设置当前采样器
|
||||
* @param sampler 采样器
|
||||
*/
|
||||
void set_sampler(sg_sampler sampler);
|
||||
|
||||
//-------------- 变换和投影 --------------
|
||||
|
||||
/**
|
||||
@ -248,6 +262,49 @@ public:
|
||||
const rect_uv& in_uv = {},
|
||||
const Eigen::Vector2f& in_scale = Eigen::Vector2f(1.f, 1.f));
|
||||
|
||||
void make_image(const Eigen::Vector2f& in_pos,
|
||||
const Eigen::Vector2f& in_size,
|
||||
const geometry_t& in_geometry,
|
||||
const sg_image& in_image,
|
||||
sampler_type in_sampler_type,
|
||||
const linear_color& in_color = { 1, 1, 1, 1 },
|
||||
const rect_uv& in_uv = {},
|
||||
float in_rotation_radians = 0.0f,
|
||||
const Eigen::Vector2f& in_pivot = Eigen::Vector2f(0.5f, 0.5f),
|
||||
const Eigen::Vector2f& in_scale = Eigen::Vector2f(1.f, 1.f));
|
||||
|
||||
void make_image(const Eigen::Vector2f& in_pos,
|
||||
const Eigen::Vector2f& in_size,
|
||||
const geometry_t& in_geometry,
|
||||
const sg_image& in_image,
|
||||
std::shared_ptr<texture_sampler> in_sampler,
|
||||
const linear_color& in_color = { 1, 1, 1, 1 },
|
||||
const rect_uv& in_uv = {},
|
||||
float in_rotation_radians = 0.0f,
|
||||
const Eigen::Vector2f& in_pivot = Eigen::Vector2f(0.5f, 0.5f),
|
||||
const Eigen::Vector2f& in_scale = Eigen::Vector2f(1.f, 1.f));
|
||||
|
||||
//-------------- 统计信息 --------------
|
||||
|
||||
/**
|
||||
* @brief 获取绘制调用次数
|
||||
* @return 绘制调用次数
|
||||
*/
|
||||
[[nodiscard]] uint32_t get_draw_call_count() const { return draw_call_count_; }
|
||||
|
||||
/**
|
||||
* @brief 获取总三角形数量
|
||||
* @return 总三角形数量
|
||||
*/
|
||||
[[nodiscard]] uint32_t get_total_triangles() const { return total_triangles_; }
|
||||
|
||||
//-------------- 禁用拷贝和赋值 --------------
|
||||
|
||||
render_elements(const render_elements&) = delete;
|
||||
render_elements& operator=(const render_elements&) = delete;
|
||||
|
||||
render_elements(render_elements&&) = delete;
|
||||
render_elements& operator=(render_elements&&) = delete;
|
||||
private:
|
||||
//-------------- 内部辅助方法 --------------
|
||||
|
||||
@ -261,8 +318,8 @@ private:
|
||||
* @param in_param_c 顶点参数C
|
||||
* @param in_uv 纹理坐标
|
||||
* @param in_rotation_radians 旋转角度
|
||||
* @param in_pivot 旋转和缩放的枢轴点
|
||||
* @param in_scale 缩放因子
|
||||
* @param in_pivot 旋转和缩放的枢轴点
|
||||
*/
|
||||
void add_rect_to_batch(const Eigen::Vector2f& in_pos,
|
||||
const Eigen::Vector2f& in_size,
|
||||
@ -272,8 +329,8 @@ private:
|
||||
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);
|
||||
const Eigen::Vector2f& in_scale,
|
||||
const Eigen::Vector2f& in_pivot);
|
||||
|
||||
/**
|
||||
* @brief 确保当前批次与给定的渲染状态兼容
|
||||
@ -342,4 +399,7 @@ private:
|
||||
|
||||
/** 圆角矩形渲染管线 */
|
||||
sg_pipeline rounded_rect_pipeline_{};
|
||||
|
||||
/** 图片渲染管线 */
|
||||
sg_pipeline image_pipeline_{};
|
||||
};
|
||||
|
@ -5,27 +5,25 @@
|
||||
#include "pixel.h"
|
||||
|
||||
/**
|
||||
* @class render_image
|
||||
* @class texture2d
|
||||
* @brief 渲染图像类
|
||||
*
|
||||
* 用于静态图片的渲染,提供创建和清除操作。
|
||||
*/
|
||||
class render_image {
|
||||
class texture2d {
|
||||
public:
|
||||
~render_image() {
|
||||
~texture2d() {
|
||||
clear();
|
||||
}
|
||||
void create(void* in_data, const Eigen::Vector2i& in_size, sg_pixel_format in_pixel_format);
|
||||
void clear() {
|
||||
if (clear_func_) {
|
||||
clear_func_();
|
||||
}
|
||||
if (sg_isvalid())
|
||||
sg_destroy_image(image_);
|
||||
}
|
||||
|
||||
[[nodiscard]] const auto& get_image() const { return image_; }
|
||||
[[nodiscard]] const auto& get_size() const { return size_; }
|
||||
private:
|
||||
std::function<void()> clear_func_{};
|
||||
sg_image image_{};
|
||||
Eigen::Vector2i size_{};
|
||||
};
|
248
src/mirage_render/render/texture_sampler.h
Normal file
248
src/mirage_render/render/texture_sampler.h
Normal file
@ -0,0 +1,248 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file sampler.h
|
||||
* @brief 跨平台纹理采样器抽象
|
||||
*/
|
||||
|
||||
#include "sokol_gfx.h"
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
class texture_sampler;
|
||||
|
||||
enum class sampler_type {
|
||||
default_,
|
||||
pixel_art,
|
||||
bilinear,
|
||||
trilinear,
|
||||
tileable,
|
||||
linear_clamp,
|
||||
shadow_map,
|
||||
anisotropic,
|
||||
};
|
||||
|
||||
/**
|
||||
* @class texture_sampler_builder
|
||||
* @brief 跨平台纹理采样器工具
|
||||
*
|
||||
* 提供简化的创建和管理纹理采样器的接口,
|
||||
* 支持流式配置风格。
|
||||
*/
|
||||
class texture_sampler_builder {
|
||||
public:
|
||||
/**
|
||||
* @brief 创建默认采样器
|
||||
* @return 具有默认配置的采样器(最近点采样,重复包裹)
|
||||
*/
|
||||
static texture_sampler_builder create_default();
|
||||
|
||||
/**
|
||||
* @brief 创建用于像素艺术的采样器(最近点采样)
|
||||
* @return 为像素艺术渲染配置的采样器
|
||||
*/
|
||||
static texture_sampler_builder create_pixel_art();
|
||||
|
||||
/**
|
||||
* @brief 创建双线性过滤采样器
|
||||
* @return 具有双线性过滤的采样器(线性过滤,无MIP映射)
|
||||
*/
|
||||
static texture_sampler_builder create_bilinear();
|
||||
|
||||
/**
|
||||
* @brief 创建三线性过滤采样器
|
||||
* @return 具有三线性过滤的采样器(带MIP映射的线性过滤)
|
||||
*/
|
||||
static texture_sampler_builder create_trilinear();
|
||||
|
||||
/**
|
||||
* @brief 创建可平铺纹理的采样器
|
||||
* @return 为可平铺纹理配置的采样器,使用线性过滤
|
||||
*/
|
||||
static texture_sampler_builder create_tileable();
|
||||
|
||||
/**
|
||||
* @brief 创建带边缘限制的线性过滤采样器
|
||||
* @return 配置为平滑渲染并带边缘限制的采样器
|
||||
*/
|
||||
static texture_sampler_builder create_linear_clamp();
|
||||
|
||||
/**
|
||||
* @brief 创建阴影贴图采样器
|
||||
* @param compare_func 阴影采样的比较函数
|
||||
* @return 为阴影贴图采样配置的采样器
|
||||
*/
|
||||
static texture_sampler_builder create_shadow_map(sg_compare_func compare_func = SG_COMPAREFUNC_LESS);
|
||||
|
||||
/**
|
||||
* @brief 创建各向异性过滤采样器
|
||||
* @param anisotropy 各向异性程度(1-16)
|
||||
* @return 具有各向异性过滤的采样器
|
||||
*/
|
||||
static texture_sampler_builder create_anisotropic(uint32_t anisotropy = 4);
|
||||
|
||||
/**
|
||||
* @brief 设置缩小过滤器
|
||||
* @param filter 用于缩小的过滤器
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_min_filter(sg_filter filter);
|
||||
|
||||
/**
|
||||
* @brief 设置放大过滤器
|
||||
* @param filter 用于放大的过滤器
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_mag_filter(sg_filter filter);
|
||||
|
||||
/**
|
||||
* @brief 设置MIP映射过滤器
|
||||
* @param filter 用于MIP映射选择的过滤器
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_mipmap_filter(sg_filter filter);
|
||||
|
||||
/**
|
||||
* @brief 同时设置所有过滤器
|
||||
* @param min_filter 缩小过滤器
|
||||
* @param mag_filter 放大过滤器
|
||||
* @param mip_filter MIP映射过滤器
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_filters(sg_filter min_filter, sg_filter mag_filter, sg_filter mip_filter);
|
||||
|
||||
/**
|
||||
* @brief 将所有过滤器设置为相同值
|
||||
* @param filter 用于所有过滤操作的过滤器
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_all_filters(sg_filter filter);
|
||||
|
||||
/**
|
||||
* @brief 设置水平包裹模式
|
||||
* @param wrap U坐标的包裹模式
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_wrap_u(sg_wrap wrap);
|
||||
|
||||
/**
|
||||
* @brief 设置垂直包裹模式
|
||||
* @param wrap V坐标的包裹模式
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_wrap_v(sg_wrap wrap);
|
||||
|
||||
/**
|
||||
* @brief 设置深度包裹模式(仅3D纹理)
|
||||
* @param wrap W坐标的包裹模式
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_wrap_w(sg_wrap wrap);
|
||||
|
||||
/**
|
||||
* @brief 同时设置所有包裹模式
|
||||
* @param wrap 所有坐标的包裹模式
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_wrap(sg_wrap wrap);
|
||||
|
||||
/**
|
||||
* @brief 单独设置所有包裹模式
|
||||
* @param wrap_u U坐标的包裹模式
|
||||
* @param wrap_v V坐标的包裹模式
|
||||
* @param wrap_w W坐标的包裹模式
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_wrap(sg_wrap wrap_u, sg_wrap wrap_v, sg_wrap wrap_w);
|
||||
|
||||
/**
|
||||
* @brief 设置LOD范围
|
||||
* @param min_lod 最小细节级别
|
||||
* @param max_lod 最大细节级别
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_lod_range(float min_lod, float max_lod);
|
||||
|
||||
/**
|
||||
* @brief 设置最小LOD级别
|
||||
* @param min_lod 最小细节级别
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_min_lod(float min_lod);
|
||||
|
||||
/**
|
||||
* @brief 设置最大LOD级别
|
||||
* @param max_lod 最大细节级别
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_max_lod(float max_lod);
|
||||
|
||||
/**
|
||||
* @brief 设置边界颜色
|
||||
* @param color 使用的边界颜色
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_border_color(sg_border_color color);
|
||||
|
||||
/**
|
||||
* @brief 设置阴影采样器的比较函数
|
||||
* @param compare 使用的比较函数
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_compare(sg_compare_func compare);
|
||||
|
||||
/**
|
||||
* @brief 设置最大各向异性级别
|
||||
* @param anisotropy 最大各向异性(1-16)
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_max_anisotropy(uint32_t anisotropy);
|
||||
|
||||
/**
|
||||
* @brief 设置调试标签
|
||||
* @param label 采样器的调试标签
|
||||
* @return 采样器引用,用于方法链式调用
|
||||
*/
|
||||
texture_sampler_builder& with_label(const char* label);
|
||||
|
||||
/**
|
||||
* @brief 构建最终的采样器描述符
|
||||
* @return 完整的采样器描述符,可用于sg_make_sampler
|
||||
*/
|
||||
sg_sampler_desc build() const;
|
||||
|
||||
/**
|
||||
* @brief 创建纹理采样器
|
||||
* @return 纹理采样器指针
|
||||
*/
|
||||
std::shared_ptr<texture_sampler> create() const;
|
||||
|
||||
static std::shared_ptr<texture_sampler> get_sampler(sampler_type in_type);
|
||||
static void clear();
|
||||
private:
|
||||
inline static std::unordered_map<sampler_type, std::shared_ptr<texture_sampler>> sampler_map_;
|
||||
|
||||
// 默认构造函数创建标准采样器配置
|
||||
texture_sampler_builder();
|
||||
|
||||
// 正在构建的采样器描述符
|
||||
sg_sampler_desc desc_;
|
||||
};
|
||||
|
||||
class texture_sampler {
|
||||
public:
|
||||
texture_sampler(const sg_sampler_desc& desc);
|
||||
~texture_sampler();
|
||||
|
||||
/**
|
||||
* @brief 获取sokol-gfx采样器句柄
|
||||
* @return sokol-gfx采样器句柄
|
||||
*/
|
||||
operator const sg_sampler&() const {
|
||||
return sampler_;
|
||||
}
|
||||
const auto& get_sampler() const { return sampler_; }
|
||||
private:
|
||||
sg_sampler sampler_{};
|
||||
};
|
@ -1,69 +0,0 @@
|
||||
#include "render/render_image.h"
|
||||
#include <dxgi1_6.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "pixel_format_convert.h"
|
||||
#include "windows_render_context.h"
|
||||
|
||||
void render_image::create(void* in_data, const Eigen::Vector2i& in_size, sg_pixel_format in_pixel_format) {
|
||||
auto render_context = mirage_render_context::get();
|
||||
if (!render_context)
|
||||
return;
|
||||
auto windows_render_context = (windows_mirage_render_context*)render_context;
|
||||
auto pixel_format = sg_pixel_format_to_dxgi(in_pixel_format);
|
||||
|
||||
// 创建D3D纹理
|
||||
D3D11_TEXTURE2D_DESC desc = {};
|
||||
desc.Width = in_size.x();
|
||||
desc.Height = in_size.y();
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = pixel_format;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
const auto& format_info = sg_query_pixelformat(in_pixel_format);
|
||||
|
||||
D3D11_SUBRESOURCE_DATA data = {};
|
||||
data.pSysMem = in_data;
|
||||
data.SysMemPitch = in_size.x() * format_info.bytes_per_pixel;
|
||||
data.SysMemSlicePitch = 0;
|
||||
|
||||
// 创建纹理
|
||||
ID3D11Texture2D* texture = nullptr;
|
||||
auto hr = windows_render_context->get_device()->CreateTexture2D(&desc, &data, &texture);
|
||||
if (FAILED(hr)) {
|
||||
std::cerr << "Failed to create texture" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建SRV
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {};
|
||||
srv_desc.Format = pixel_format;
|
||||
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srv_desc.Texture2D.MostDetailedMip = 0;
|
||||
srv_desc.Texture2D.MipLevels = 1;
|
||||
|
||||
ID3D11ShaderResourceView* srv = nullptr;
|
||||
hr = windows_render_context->get_device()->CreateShaderResourceView(texture, &srv_desc, &srv);
|
||||
if (FAILED(hr)) {
|
||||
texture->Release();
|
||||
std::cerr << "Failed to create shader resource view" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
clear_func_ = [=] {
|
||||
texture->Release();
|
||||
srv->Release();
|
||||
};
|
||||
|
||||
sg_image_desc sg_desc{};
|
||||
sg_desc.d3d11_texture = texture;
|
||||
sg_desc.d3d11_shader_resource_view = srv;
|
||||
|
||||
image_ = sg_make_image(sg_desc);
|
||||
}
|
25
src/mirage_render/render/windows/texture2d.cpp
Normal file
25
src/mirage_render/render/windows/texture2d.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "render/texture2d.h"
|
||||
#include <dxgi1_6.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "pixel_format_convert.h"
|
||||
#include "windows_render_context.h"
|
||||
|
||||
void texture2d::create(void* in_data, const Eigen::Vector2i& in_size, sg_pixel_format in_pixel_format) {
|
||||
auto format_info = sg_query_pixelformat(in_pixel_format);
|
||||
|
||||
sg_image_desc sg_desc{};
|
||||
sg_desc.type = SG_IMAGETYPE_2D;
|
||||
sg_desc.render_target = false;
|
||||
sg_desc.width = in_size.x();
|
||||
sg_desc.height = in_size.y();
|
||||
sg_desc.num_slices = 1;
|
||||
sg_desc.num_mipmaps = 1;
|
||||
sg_desc.usage = SG_USAGE_IMMUTABLE;
|
||||
sg_desc.pixel_format = in_pixel_format;
|
||||
sg_desc.sample_count = 1;
|
||||
sg_desc.data.subimage[0][0].ptr = in_data;
|
||||
sg_desc.data.subimage[0][0].size = in_size.x() * in_size.y() * format_info.bytes_per_pixel;
|
||||
|
||||
image_ = sg_make_image(sg_desc);
|
||||
}
|
234
src/mirage_render/render/windows/texture_sampler.cpp
Normal file
234
src/mirage_render/render/windows/texture_sampler.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
#include "render/texture_sampler.h"
|
||||
#include <algorithm> // For std::clamp
|
||||
#include <iostream>
|
||||
|
||||
// 默认构造函数,设置标准配置
|
||||
texture_sampler_builder::texture_sampler_builder() {
|
||||
// 初始化默认值
|
||||
desc_ = {}; // 零初始化所有字段
|
||||
|
||||
// 根据sg_sampler_desc默认值设置
|
||||
desc_.min_filter = SG_FILTER_NEAREST;
|
||||
desc_.mag_filter = SG_FILTER_NEAREST;
|
||||
desc_.mipmap_filter = SG_FILTER_NEAREST;
|
||||
desc_.wrap_u = SG_WRAP_REPEAT;
|
||||
desc_.wrap_v = SG_WRAP_REPEAT;
|
||||
desc_.wrap_w = SG_WRAP_REPEAT;
|
||||
desc_.min_lod = 0.0f;
|
||||
desc_.max_lod = std::numeric_limits<float>::max();
|
||||
desc_.border_color = SG_BORDERCOLOR_OPAQUE_BLACK;
|
||||
desc_.compare = SG_COMPAREFUNC_NEVER;
|
||||
desc_.max_anisotropy = 1;
|
||||
}
|
||||
|
||||
// 常用采样器类型的静态工厂方法
|
||||
texture_sampler_builder texture_sampler_builder::create_default() {
|
||||
return texture_sampler_builder();
|
||||
}
|
||||
|
||||
texture_sampler_builder texture_sampler_builder::create_pixel_art() {
|
||||
return texture_sampler_builder()
|
||||
.with_all_filters(SG_FILTER_NEAREST)
|
||||
.with_wrap(SG_WRAP_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
texture_sampler_builder texture_sampler_builder::create_bilinear() {
|
||||
return texture_sampler_builder()
|
||||
.with_min_filter(SG_FILTER_LINEAR)
|
||||
.with_mag_filter(SG_FILTER_LINEAR)
|
||||
.with_mipmap_filter(SG_FILTER_NEAREST);
|
||||
}
|
||||
|
||||
texture_sampler_builder texture_sampler_builder::create_trilinear() {
|
||||
return texture_sampler_builder()
|
||||
.with_all_filters(SG_FILTER_LINEAR);
|
||||
}
|
||||
|
||||
texture_sampler_builder texture_sampler_builder::create_tileable() {
|
||||
return texture_sampler_builder()
|
||||
.with_all_filters(SG_FILTER_LINEAR)
|
||||
.with_wrap(SG_WRAP_REPEAT);
|
||||
}
|
||||
|
||||
texture_sampler_builder texture_sampler_builder::create_linear_clamp() {
|
||||
return texture_sampler_builder()
|
||||
.with_all_filters(SG_FILTER_LINEAR)
|
||||
.with_wrap(SG_WRAP_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
texture_sampler_builder texture_sampler_builder::create_shadow_map(sg_compare_func compare_func) {
|
||||
return texture_sampler_builder()
|
||||
.with_min_filter(SG_FILTER_LINEAR)
|
||||
.with_mag_filter(SG_FILTER_LINEAR)
|
||||
.with_wrap(SG_WRAP_CLAMP_TO_EDGE)
|
||||
.with_compare(compare_func)
|
||||
.with_border_color(SG_BORDERCOLOR_OPAQUE_WHITE);
|
||||
}
|
||||
|
||||
texture_sampler_builder texture_sampler_builder::create_anisotropic(uint32_t anisotropy) {
|
||||
return texture_sampler_builder()
|
||||
.with_all_filters(SG_FILTER_LINEAR)
|
||||
.with_max_anisotropy(anisotropy);
|
||||
}
|
||||
|
||||
// 流式接口配置方法
|
||||
texture_sampler_builder& texture_sampler_builder::with_min_filter(sg_filter filter) {
|
||||
desc_.min_filter = filter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_mag_filter(sg_filter filter) {
|
||||
desc_.mag_filter = filter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_mipmap_filter(sg_filter filter) {
|
||||
desc_.mipmap_filter = filter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_filters(sg_filter min_filter, sg_filter mag_filter, sg_filter mip_filter) {
|
||||
desc_.min_filter = min_filter;
|
||||
desc_.mag_filter = mag_filter;
|
||||
desc_.mipmap_filter = mip_filter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_all_filters(sg_filter filter) {
|
||||
return with_filters(filter, filter, filter);
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_wrap_u(sg_wrap wrap) {
|
||||
desc_.wrap_u = wrap;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_wrap_v(sg_wrap wrap) {
|
||||
desc_.wrap_v = wrap;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_wrap_w(sg_wrap wrap) {
|
||||
desc_.wrap_w = wrap;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_wrap(sg_wrap wrap) {
|
||||
desc_.wrap_u = wrap;
|
||||
desc_.wrap_v = wrap;
|
||||
desc_.wrap_w = wrap;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_wrap(sg_wrap wrap_u, sg_wrap wrap_v, sg_wrap wrap_w) {
|
||||
desc_.wrap_u = wrap_u;
|
||||
desc_.wrap_v = wrap_v;
|
||||
desc_.wrap_w = wrap_w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_lod_range(float min_lod, float max_lod) {
|
||||
// 确保min_lod <= max_lod
|
||||
if (min_lod > max_lod) {
|
||||
std::swap(min_lod, max_lod);
|
||||
}
|
||||
|
||||
desc_.min_lod = min_lod;
|
||||
desc_.max_lod = max_lod;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_min_lod(float min_lod) {
|
||||
desc_.min_lod = min_lod;
|
||||
// 确保min_lod <= max_lod
|
||||
if (min_lod > desc_.max_lod) {
|
||||
desc_.max_lod = min_lod;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_max_lod(float max_lod) {
|
||||
desc_.max_lod = max_lod;
|
||||
// 确保min_lod <= max_lod
|
||||
if (desc_.min_lod > max_lod) {
|
||||
desc_.min_lod = max_lod;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_border_color(sg_border_color color) {
|
||||
desc_.border_color = color;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_compare(sg_compare_func compare) {
|
||||
desc_.compare = compare;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_max_anisotropy(uint32_t anisotropy) {
|
||||
// 确保各向异性在有效范围内
|
||||
desc_.max_anisotropy = std::clamp(anisotropy, 1u, 16u);
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_sampler_builder& texture_sampler_builder::with_label(const char* label) {
|
||||
desc_.label = label;
|
||||
return *this;
|
||||
}
|
||||
|
||||
sg_sampler_desc texture_sampler_builder::build() const {
|
||||
return desc_;
|
||||
}
|
||||
|
||||
std::shared_ptr<texture_sampler> texture_sampler_builder::create() const {
|
||||
return std::make_shared<texture_sampler>(build());
|
||||
}
|
||||
|
||||
std::shared_ptr<texture_sampler> texture_sampler_builder::get_sampler(sampler_type in_type) {
|
||||
// 尝试从sampler_map_中查找
|
||||
const auto& it = sampler_map_.find(in_type);
|
||||
if (it != sampler_map_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// 如果没有找到,创建新的采样器并存储
|
||||
switch (in_type) {
|
||||
case sampler_type::default_:
|
||||
return sampler_map_[in_type] = create_default().create();
|
||||
case sampler_type::pixel_art:
|
||||
return sampler_map_[in_type] = create_pixel_art().create();
|
||||
case sampler_type::bilinear:
|
||||
return sampler_map_[in_type] = create_bilinear().create();
|
||||
case sampler_type::trilinear:
|
||||
return sampler_map_[in_type] = create_trilinear().create();
|
||||
case sampler_type::tileable:
|
||||
return sampler_map_[in_type] = create_tileable().create();
|
||||
case sampler_type::linear_clamp:
|
||||
return sampler_map_[in_type] = create_linear_clamp().create();
|
||||
case sampler_type::shadow_map:
|
||||
return sampler_map_[in_type] = create_shadow_map().create();
|
||||
case sampler_type::anisotropic:
|
||||
return sampler_map_[in_type] = create_anisotropic().create();
|
||||
}
|
||||
|
||||
// 未知类型
|
||||
std::cerr << "Unknown sampler type: " << static_cast<int>(in_type) << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void texture_sampler_builder::clear() {
|
||||
sampler_map_.clear();
|
||||
}
|
||||
|
||||
texture_sampler::texture_sampler(const sg_sampler_desc& desc) {
|
||||
sampler_ = sg_make_sampler(desc);
|
||||
}
|
||||
|
||||
texture_sampler::~texture_sampler() {
|
||||
if (sampler_.id != SG_INVALID_ID) {
|
||||
if (sg_isvalid())
|
||||
sg_destroy_sampler(sampler_);
|
||||
}
|
||||
}
|
||||
|
35
src/mirage_render/shaders/mirage_image.slang
Normal file
35
src/mirage_render/shaders/mirage_image.slang
Normal file
@ -0,0 +1,35 @@
|
||||
#include "mirage_util.slang"
|
||||
|
||||
cbuffer ParamBuffer
|
||||
{
|
||||
matrix transform;
|
||||
};
|
||||
|
||||
SamplerState textureSampler;
|
||||
Texture2D texture;
|
||||
|
||||
struct PSInput {
|
||||
float4 position : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
[shader("vertex")]
|
||||
PSInput vertex_main(VSInput input)
|
||||
{
|
||||
PSInput output;
|
||||
|
||||
// 并通过常量缓冲区或结构化缓冲区传递
|
||||
output.position = mul(float4(input.position, 0.0, 1.0), transform);
|
||||
output.uv = input.uv;
|
||||
output.color = input.color;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("pixel")]
|
||||
float4 pixel_main(PSInput input) : SV_Target
|
||||
{
|
||||
float4 color = texture.Sample(textureSampler, input.uv);
|
||||
return color * input.color;
|
||||
}
|
@ -1 +1,25 @@
|
||||
#include "mimage.h"
|
||||
|
||||
#include "render/texture2d.h"
|
||||
|
||||
void mimage::on_paint(mirage_paint_context& in_context) {
|
||||
if (!image_) {
|
||||
return;
|
||||
}
|
||||
|
||||
in_context.drawer().make_image(
|
||||
{ 0, 0 },
|
||||
in_context.geo().get_local_size(),
|
||||
in_context.geo(),
|
||||
image_->get_image(),
|
||||
sampler_type::default_,
|
||||
{ color_ }
|
||||
);
|
||||
}
|
||||
|
||||
Eigen::Vector2f mimage::compute_desired_size(float in_layout_scale_multiplier) const {
|
||||
if (image_) {
|
||||
return image_->get_size().cast<float>();
|
||||
}
|
||||
return { 20, 20 };
|
||||
}
|
||||
|
@ -1,10 +1,21 @@
|
||||
#pragma once
|
||||
#include "render/texture_sampler.h"
|
||||
#include "widget/mleaf_widget.h"
|
||||
|
||||
class texture2d;
|
||||
|
||||
class mimage : public mleaf_widget {
|
||||
public:
|
||||
virtual void on_paint(mirage_paint_context& in_context) override;
|
||||
virtual Eigen::Vector2f compute_desired_size(float in_layout_scale_multiplier) const override;
|
||||
private:
|
||||
void on_paint(mirage_paint_context& in_context) override;
|
||||
Eigen::Vector2f compute_desired_size(float in_layout_scale_multiplier) const override;
|
||||
|
||||
const auto& get_image() const { return image_; }
|
||||
void set_image(const std::shared_ptr<texture2d>& in_image) { image_ = in_image; }
|
||||
|
||||
const auto& get_color() const { return color_; }
|
||||
void set_color(const linear_color& in_color) { color_ = in_color; }
|
||||
private:
|
||||
std::shared_ptr<texture2d> image_;
|
||||
std::shared_ptr<texture_sampler> sampler_;
|
||||
linear_color color_ = { 1, 1, 1, 1 };
|
||||
};
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user