图片绘制

This commit is contained in:
Nanako 2025-03-26 22:17:11 +08:00
parent 2c5ea1e7e9
commit dc896d51f3
13 changed files with 740 additions and 122 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View 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_{};
};

View File

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

View 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);
}

View 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_);
}
}

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

View File

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

View File

@ -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.