线框着色器和线段着色器
This commit is contained in:
parent
56917da0d1
commit
673b0a1478
@ -12,10 +12,11 @@ int main(int argc, char* argv[]) {
|
||||
auto& manager = font_manager::instance();
|
||||
manager.add_font(L"C:/Users/46944/AppData/Local/Microsoft/Windows/Fonts/MapleMono-NF-CN-Regular.ttf");
|
||||
manager.add_font(L"C:/Windows/Fonts/msyh.ttc");
|
||||
// manager.add_font(L"D:/Projects/noto-emoji-2.047/fonts/Noto-COLRv1.ttf");
|
||||
manager.add_font(L"C:/Windows/Fonts/seguiemj.ttf");
|
||||
|
||||
const auto& text_block = std::make_shared<mtext_block>();
|
||||
text_block->set_text(U"Hello, World! 你好,世界!😀");
|
||||
text_block->set_text(U"Hello, World! 你好,世界!🥶😅😎");
|
||||
|
||||
const auto& text_block2 = std::make_shared<mtext_block>();
|
||||
text_block2->set_text(U"Hello, World!");
|
||||
|
@ -163,6 +163,18 @@ public:
|
||||
*/
|
||||
const auto& size() const { return size_; }
|
||||
|
||||
/**
|
||||
* @brief 获取位置
|
||||
* @return 矩形位置
|
||||
*/
|
||||
auto& position() { return position_; }
|
||||
|
||||
/**
|
||||
* @brief 获取大小
|
||||
* @return 矩形大小
|
||||
*/
|
||||
auto& size() { return size_; }
|
||||
|
||||
/**
|
||||
* @brief 获取左边界
|
||||
* @return 左边界位置
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
int width, height, xoff, yoff;
|
||||
auto bitmap = stbtt_GetGlyphBitmap(&in_font.get_font_info(), scale, scale, in_glyph_index,
|
||||
&width, &height, &xoff, &yoff);
|
||||
// stbtt_GetGlyphSDF();
|
||||
|
||||
if (!bitmap || width == 0 || height == 0) {
|
||||
result.reason = glyph_atlas_reason_t::glyph_not_found;
|
||||
|
@ -46,6 +46,12 @@ float font_face_t::get_scale_for_pixel_height(float font_size) const {
|
||||
return stbtt_ScaleForPixelHeight(&font_info_, font_size);
|
||||
}
|
||||
|
||||
float font_face_t::get_line_height() const {
|
||||
// 获取字体的行高
|
||||
const auto v_metrics = get_v_metrics();
|
||||
return static_cast<float>(v_metrics.ascent - v_metrics.descent + v_metrics.line_gap);
|
||||
}
|
||||
|
||||
std::optional<glyph_t> font_face_t::get_glyph(int32_t code_point, float font_size) const {
|
||||
// 获取字形索引
|
||||
const auto glyph_index = find_glyph_index(code_point);
|
||||
|
@ -62,6 +62,12 @@ public:
|
||||
*/
|
||||
float get_scale_for_pixel_height(float font_size) const;
|
||||
|
||||
/**
|
||||
* @brief 获取字体的行高
|
||||
* @return 行高值
|
||||
*/
|
||||
[[nodiscard]] float get_line_height() const;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// 字形信息查询
|
||||
//--------------------------------------------------------------------------
|
||||
|
@ -60,14 +60,29 @@ std::optional<color_emoji_bitmap_t> colr_renderer_t::render_emoji(
|
||||
const uint16_t first_layer_index = font::read_u16(target_record + 2);
|
||||
const uint16_t num_layers_for_glyph = font::read_u16(target_record + 4);
|
||||
|
||||
// 解析CPAL表
|
||||
// 检查图层数量
|
||||
if (num_layers_for_glyph == 0 || first_layer_index + num_layers_for_glyph > num_layers) {
|
||||
return std::nullopt; // 无效的图层配置
|
||||
}
|
||||
|
||||
// 解析CPAL表 - 为Windows字体特别处理
|
||||
const uint16_t cpal_version = font::read_u16(cpal_data);
|
||||
const uint16_t num_palette_entries = font::read_u16(cpal_data + 2);
|
||||
const uint16_t num_palettes = font::read_u16(cpal_data + 4);
|
||||
const uint32_t color_records_offset = font::read_u32(cpal_data + 8);
|
||||
|
||||
// Windows字体可能有类型选择器字段
|
||||
uint16_t color_record_indices_offset = 12;
|
||||
if (cpal_version > 0 && cpal_data + 12 < font_data + font_offset + color_records_offset) {
|
||||
color_record_indices_offset = 14; // 调整CPAL格式偏移
|
||||
}
|
||||
|
||||
// 使用第一个调色板
|
||||
const uint8_t* palette_indices = cpal_data + 12;
|
||||
const uint16_t first_color_index = font::read_u16(palette_indices);
|
||||
const uint8_t* palette_indices = cpal_data + color_record_indices_offset;
|
||||
uint16_t first_color_index = 0;
|
||||
if (num_palettes > 0) {
|
||||
first_color_index = font::read_u16(palette_indices);
|
||||
}
|
||||
|
||||
// 计算缩放比例
|
||||
const float scale = stbtt_ScaleForPixelHeight(&font_info, font_size);
|
||||
@ -81,36 +96,50 @@ std::optional<color_emoji_bitmap_t> colr_renderer_t::render_emoji(
|
||||
bitmap.width = x1 - x0;
|
||||
bitmap.height = y1 - y0;
|
||||
|
||||
// 确保位图尺寸有效
|
||||
// 确保位图尺寸有效 - Windows字体可能需要额外的填充
|
||||
if (bitmap.width <= 0 || bitmap.height <= 0) {
|
||||
bitmap.width = static_cast<int>(font_size);
|
||||
bitmap.height = static_cast<int>(font_size);
|
||||
bitmap.width = static_cast<int>(font_size * 1.2); // 添加额外空间
|
||||
bitmap.height = static_cast<int>(font_size * 1.2);
|
||||
x0 = 0;
|
||||
y0 = 0;
|
||||
}
|
||||
|
||||
// 初始化RGBA位图数据
|
||||
bitmap.data.resize(bitmap.width * bitmap.height * 4, 0);
|
||||
|
||||
// 渲染每一个图层
|
||||
// 渲染每一个图层 - Windows Segoe UI Emoji特别处理
|
||||
const uint8_t* layer_records = colr_data + layer_records_offset;
|
||||
const uint8_t* color_records = cpal_data + color_records_offset;
|
||||
|
||||
// 处理Microsoft特有的图层顺序
|
||||
for (uint16_t i = 0; i < num_layers_for_glyph; i++) {
|
||||
const uint8_t* layer = layer_records + (first_layer_index + i) * 4;
|
||||
const uint16_t layer_glyph_id = font::read_u16(layer);
|
||||
const uint16_t palette_entry_index = font::read_u16(layer + 2);
|
||||
|
||||
// 获取颜色
|
||||
// 确保层索引有效
|
||||
if (palette_entry_index >= num_palette_entries) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取颜色 - Windows字体可能有不同的颜色格式
|
||||
const uint16_t color_index = first_color_index + palette_entry_index;
|
||||
if (color_index >= num_palette_entries) {
|
||||
continue; // 超出调色板范围
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint8_t* color = color_records + color_index * 4;
|
||||
// Windows字体通常使用BGRA顺序
|
||||
const uint8_t blue = color[0];
|
||||
const uint8_t green = color[1];
|
||||
const uint8_t red = color[2];
|
||||
const uint8_t alpha = color[3];
|
||||
|
||||
// Windows字体可能会对特定颜色设置特殊意义
|
||||
// 如果alpha为0,微软通常将其视为"不透明黑色"
|
||||
const uint8_t effective_alpha = (alpha == 0 && (red > 0 || green > 0 || blue > 0))
|
||||
? 255 : alpha;
|
||||
|
||||
// 为图层创建临时位图
|
||||
int layer_x0, layer_y0, layer_x1, layer_y1;
|
||||
stbtt_GetGlyphBitmapBox(&font_info, layer_glyph_id, scale, scale,
|
||||
@ -120,11 +149,13 @@ std::optional<color_emoji_bitmap_t> colr_renderer_t::render_emoji(
|
||||
const int layer_height = layer_y1 - layer_y0;
|
||||
|
||||
if (layer_width <= 0 || layer_height <= 0) {
|
||||
continue; // 跳过无效尺寸的图层
|
||||
continue;
|
||||
}
|
||||
|
||||
// 渲染图层字形的灰度位图
|
||||
std::vector<uint8_t> layer_bitmap(layer_width * layer_height, 0);
|
||||
|
||||
// 使用更高精度的渲染方法 - 关键是对细节(如眼睛)的处理
|
||||
stbtt_MakeGlyphBitmap(&font_info, layer_bitmap.data(),
|
||||
layer_width, layer_height, layer_width,
|
||||
scale, scale, layer_glyph_id);
|
||||
@ -133,7 +164,7 @@ std::optional<color_emoji_bitmap_t> colr_renderer_t::render_emoji(
|
||||
const int offset_x = layer_x0 - x0;
|
||||
const int offset_y = layer_y0 - y0;
|
||||
|
||||
// 将图层与颜色混合到最终位图
|
||||
// 将图层与颜色混合到最终位图 - Windows样式混合
|
||||
for (int y = 0; y < layer_height; y++) {
|
||||
const int dst_y = offset_y + y;
|
||||
if (dst_y < 0 || dst_y >= bitmap.height) {
|
||||
@ -148,23 +179,45 @@ std::optional<color_emoji_bitmap_t> colr_renderer_t::render_emoji(
|
||||
|
||||
const uint8_t coverage = layer_bitmap[y * layer_width + x];
|
||||
if (coverage == 0) {
|
||||
continue; // 跳过透明像素
|
||||
continue;
|
||||
}
|
||||
|
||||
const int dst_idx = (dst_y * bitmap.width + dst_x) * 4;
|
||||
|
||||
// Alpha混合
|
||||
const float src_alpha = (coverage / 255.0f) * (alpha / 255.0f);
|
||||
const float dst_alpha = bitmap.data[dst_idx + 3] / 255.0f;
|
||||
const float out_alpha = src_alpha + dst_alpha * (1.0f - src_alpha);
|
||||
// Windows风格的Alpha混合 - 这对眼睛等小细节很重要
|
||||
const float src_alpha = (coverage / 255.0f) * (effective_alpha / 255.0f);
|
||||
|
||||
if (out_alpha > 0) {
|
||||
bitmap.data[dst_idx + 0] = static_cast<uint8_t>((red * src_alpha + bitmap.data[dst_idx + 0] * dst_alpha * (1.0f - src_alpha)) / out_alpha);
|
||||
bitmap.data[dst_idx + 1] = static_cast<uint8_t>((green * src_alpha + bitmap.data[dst_idx + 1] * dst_alpha * (1.0f - src_alpha)) / out_alpha);
|
||||
bitmap.data[dst_idx + 2] = static_cast<uint8_t>((blue * src_alpha + bitmap.data[dst_idx + 2] * dst_alpha * (1.0f - src_alpha)) / out_alpha);
|
||||
// 对于细节图层(如眼睛),增强其影响
|
||||
float enhanced_alpha = src_alpha;
|
||||
if (palette_entry_index > 0 && src_alpha > 0) { // 非底色图层且有透明度
|
||||
enhanced_alpha = std::min(src_alpha * 1.2f, 1.0f); // 稍微增强
|
||||
}
|
||||
|
||||
bitmap.data[dst_idx + 3] = static_cast<uint8_t>(out_alpha * 255.0f);
|
||||
const float dst_alpha = bitmap.data[dst_idx + 3] / 255.0f;
|
||||
const float out_alpha = enhanced_alpha + dst_alpha * (1.0f - enhanced_alpha);
|
||||
|
||||
if (out_alpha > 0) {
|
||||
// 特别处理黑色或暗色像素,这通常是眼睛等细节
|
||||
if (red <= 64 && green <= 64 && blue <= 64 && enhanced_alpha > 0.2f) {
|
||||
// 增强黑色细节的可见度
|
||||
bitmap.data[dst_idx + 0] = red;
|
||||
bitmap.data[dst_idx + 1] = green;
|
||||
bitmap.data[dst_idx + 2] = blue;
|
||||
bitmap.data[dst_idx + 3] = static_cast<uint8_t>(enhanced_alpha * 255.0f);
|
||||
} else {
|
||||
// 标准混合
|
||||
const float src_factor = enhanced_alpha / out_alpha;
|
||||
const float dst_factor = dst_alpha * (1.0f - enhanced_alpha) / out_alpha;
|
||||
|
||||
bitmap.data[dst_idx + 0] = static_cast<uint8_t>(
|
||||
std::min(255.0f, red * src_factor + bitmap.data[dst_idx + 0] * dst_factor));
|
||||
bitmap.data[dst_idx + 1] = static_cast<uint8_t>(
|
||||
std::min(255.0f, green * src_factor + bitmap.data[dst_idx + 1] * dst_factor));
|
||||
bitmap.data[dst_idx + 2] = static_cast<uint8_t>(
|
||||
std::min(255.0f, blue * src_factor + bitmap.data[dst_idx + 2] * dst_factor));
|
||||
bitmap.data[dst_idx + 3] = static_cast<uint8_t>(out_alpha * 255.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,13 +81,13 @@ text_layout_t font_manager::layout_text(
|
||||
// 初始化布局变量
|
||||
float cursor_x = 0.0f;
|
||||
float cursor_y = 0.0f;
|
||||
const float line_height = font_size * line_spacing;
|
||||
const float line_height = primary_font->get_line_height() * scale + line_spacing;
|
||||
float line_max_width = 0.0f;
|
||||
|
||||
const auto& v_metrics = primary_font->get_v_metrics();
|
||||
|
||||
float font_ascent = v_metrics.ascent * scale;
|
||||
float line_max_descent = std::abs(v_metrics.descent * scale);
|
||||
float font_descent = std::abs(v_metrics.descent * scale);
|
||||
|
||||
int32_t last_index = 0; // 上一个字形索引,用于字距调整
|
||||
float line_start_x = 0.0f; // 当前行的起始x坐标
|
||||
@ -112,10 +112,12 @@ text_layout_t font_manager::layout_text(
|
||||
|
||||
// 重置为下一行的基线计算
|
||||
font_ascent = v_metrics.ascent * scale;
|
||||
line_max_descent = std::abs(v_metrics.descent * scale);
|
||||
font_descent = std::abs(v_metrics.descent * scale);
|
||||
baseline = cursor_y + font_ascent;
|
||||
};
|
||||
|
||||
layout.ascent = font_ascent;
|
||||
|
||||
// 处理每个字符
|
||||
for (const auto& c : text) {
|
||||
// 检查是否是换行符
|
||||
@ -162,7 +164,8 @@ text_layout_t font_manager::layout_text(
|
||||
|
||||
// 计算字形坐标
|
||||
float x = cursor_x + glyph_metrics->lsb + glyph_metrics->rect.left();
|
||||
float y = cursor_y + font_ascent + glyph_metrics->rect.top();
|
||||
// float y = cursor_y + font_ascent + glyph_metrics->rect.top() + font_descent;
|
||||
float y = baseline + glyph_metrics->rect.top();
|
||||
|
||||
// 添加字形位置信息到布局
|
||||
auto& glyph_position = layout.glyphs.emplace_back();
|
||||
|
@ -142,8 +142,10 @@ struct text_layout_t {
|
||||
atlas_region_t region; // 纹理图集区域
|
||||
};
|
||||
|
||||
std::vector<glyph_position_t> glyphs; // 所有字形位置
|
||||
Eigen::Vector2f total_size; // 文本总尺寸
|
||||
std::vector<glyph_position_t> glyphs; // 所有字形位置
|
||||
Eigen::Vector2f total_size; // 文本总尺寸
|
||||
float ascent; // 上升高度
|
||||
float baseline = 0.0f; // 基线位置
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "shaders/mirage_rounded_rect.hlsl.h"
|
||||
#include "shaders/mirage_image.hlsl.h"
|
||||
#include "shaders/mirage_text.hlsl.h"
|
||||
#include "shaders/mirage_wireframe.hlsl.h"
|
||||
#include "shaders/mirage_line.hlsl.h"
|
||||
|
||||
template<typename Derived>
|
||||
void compute_rect_vertices(const Eigen::MatrixBase<Derived>& in_pos,
|
||||
@ -187,6 +189,7 @@ void render_elements::make_rect(
|
||||
float in_rotation_radians,
|
||||
const Eigen::Vector2f& in_pivot,
|
||||
const Eigen::Vector2f& in_scale) {
|
||||
// 从几何体转换到窗口坐标
|
||||
const auto& pos = in_geometry.local_to_window(in_pos);
|
||||
add_rect_to_batch(pos,
|
||||
in_size,
|
||||
@ -263,12 +266,87 @@ void render_elements::make_text(const text_layout_t& in_layout, const Eigen::Vec
|
||||
new_key.image = texture->get_image();
|
||||
new_key.sampler = *sampler;
|
||||
|
||||
const Eigen::Vector2f& real_pos = p.position.array() + in_pos.array();
|
||||
Eigen::Vector2f real_pos = p.position.array() + in_pos.array();
|
||||
// snap to pixel grid
|
||||
real_pos.x() = std::round(real_pos.x());
|
||||
real_pos.y() = std::round(real_pos.y());
|
||||
|
||||
ensure_batch_compatibility(new_key);
|
||||
make_rect(real_pos, size, in_color, in_geometry, {}, {}, {}, uv, in_rotation_radians, in_pivot, in_scale);
|
||||
// make_wireframe(real_pos, size, in_geometry, 1.0f, in_color, in_rotation_radians, in_pivot, in_scale);
|
||||
}
|
||||
}
|
||||
Eigen::Vector2f font_ascent_start = in_pos;
|
||||
font_ascent_start.y() += in_layout.ascent;
|
||||
Eigen::Vector2f font_ascent_end = font_ascent_start;
|
||||
font_ascent_end.x() += in_layout.total_size.x();
|
||||
|
||||
// 绘制文本的基线
|
||||
make_line(font_ascent_start, font_ascent_end, in_geometry, 1.0f, in_color, in_rotation_radians, in_pivot, in_scale);
|
||||
// 绘制文本的线框
|
||||
make_wireframe(in_pos, in_size, in_geometry, 1.0f, in_color, in_rotation_radians, in_pivot, in_scale);
|
||||
}
|
||||
|
||||
void render_elements::make_wireframe(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size,
|
||||
const geometry_t& in_geometry, float in_line_width, const rect_color& in_color, float in_rotation_radians,
|
||||
const Eigen::Vector2f& in_pivot, const Eigen::Vector2f& in_scale) {
|
||||
set_pipeline(wireframe_pipeline_);
|
||||
mirage_vertex_param_t param_a{};
|
||||
param_a.x = in_line_width / in_size.x();
|
||||
param_a.y = in_line_width / in_size.y();
|
||||
make_rect(in_pos,
|
||||
in_size,
|
||||
{ in_color },
|
||||
in_geometry,
|
||||
param_a,
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
in_rotation_radians,
|
||||
in_pivot,
|
||||
in_scale);
|
||||
}
|
||||
|
||||
void render_elements::make_line(const Eigen::Vector2f& in_start, const Eigen::Vector2f& in_end,
|
||||
const geometry_t& in_geometry, float in_thickness, const rect_color& in_color, float in_rotation_radians,
|
||||
const Eigen::Vector2f& in_pivot, const Eigen::Vector2f& in_scale) {
|
||||
set_pipeline(line_pipeline_);
|
||||
auto rect = rect_t<>::bounding_box<float>({in_start, in_end});
|
||||
|
||||
if (rect.size().x() == 0 || rect.size().y() == 0) {
|
||||
// 根据线段方向添加厚度
|
||||
Eigen::Vector2f direction = (in_end - in_start).normalized();
|
||||
Eigen::Vector2f normal = Eigen::Vector2f(-direction.y(), direction.x());
|
||||
rect.position() -= normal * in_thickness * 0.5f;
|
||||
rect.size() += normal * in_thickness;
|
||||
}
|
||||
|
||||
mirage_vertex_param_t param_a{};
|
||||
mirage_vertex_param_t param_b{};
|
||||
param_a.x = in_thickness;
|
||||
|
||||
// 需要将线段的起始和结束点转换为窗口坐标, 因为着色器中使用的是窗口坐标
|
||||
const auto& start_window = in_geometry.local_to_window(in_start);
|
||||
const auto& end_window = in_geometry.local_to_window(in_end);
|
||||
|
||||
param_b.x = start_window.x();
|
||||
param_b.y = start_window.y();
|
||||
param_b.z = end_window.x();
|
||||
param_b.w = end_window.y();
|
||||
|
||||
make_rect(
|
||||
rect.position(),
|
||||
rect.size(),
|
||||
{ in_color },
|
||||
in_geometry,
|
||||
param_a,
|
||||
param_b,
|
||||
{},
|
||||
{},
|
||||
in_rotation_radians,
|
||||
in_pivot,
|
||||
in_scale
|
||||
);
|
||||
}
|
||||
|
||||
// 确保缓冲区容量
|
||||
@ -383,4 +461,12 @@ void render_elements::load_mirage_pipelines() {
|
||||
const auto font_shader = sg_make_shader(get_mirage_text_shader_desc());
|
||||
const auto font_pipeline_desc = get_mirage_text_pipeline_desc(font_shader, format, 1);
|
||||
text_pipeline_ = sg_make_pipeline(font_pipeline_desc);
|
||||
|
||||
const auto wireframe_shader = sg_make_shader(get_mirage_wireframe_shader_desc());
|
||||
const auto wireframe_pipeline_desc = get_mirage_wireframe_pipeline_desc(wireframe_shader, format, 1);
|
||||
wireframe_pipeline_ = sg_make_pipeline(wireframe_pipeline_desc);
|
||||
|
||||
const auto line_shader = sg_make_shader(get_mirage_line_shader_desc());
|
||||
const auto line_pipeline_desc = get_mirage_line_pipeline_desc(line_shader, format, 1);
|
||||
line_pipeline_ = sg_make_pipeline(line_pipeline_desc);
|
||||
}
|
||||
|
@ -270,6 +270,24 @@ public:
|
||||
const Eigen::Vector2f& in_pivot = Eigen::Vector2f(0.5f, 0.5f),
|
||||
const Eigen::Vector2f& in_scale = Eigen::Vector2f(1.f, 1.f));
|
||||
|
||||
void make_wireframe(const Eigen::Vector2f& in_pos,
|
||||
const Eigen::Vector2f& in_size,
|
||||
const geometry_t& in_geometry,
|
||||
float in_line_width,
|
||||
const rect_color& in_color = { { 1, 1, 1, 1 } },
|
||||
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_line(const Eigen::Vector2f& in_start,
|
||||
const Eigen::Vector2f& in_end,
|
||||
const geometry_t& in_geometry,
|
||||
float in_thickness,
|
||||
const rect_color& in_color = { { 1, 1, 1, 1 } },
|
||||
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));
|
||||
|
||||
//-------------- 统计信息 --------------
|
||||
|
||||
/**
|
||||
@ -391,4 +409,10 @@ private:
|
||||
|
||||
/** 文本渲染管线 */
|
||||
sg_pipeline text_pipeline_{};
|
||||
|
||||
/** 线框渲染管线 */
|
||||
sg_pipeline wireframe_pipeline_{};
|
||||
|
||||
/** 线条渲染管线 */
|
||||
sg_pipeline line_pipeline_{};
|
||||
};
|
||||
|
45
src/mirage_render/shaders/mirage_wireframe.slang
Normal file
45
src/mirage_render/shaders/mirage_wireframe.slang
Normal file
@ -0,0 +1,45 @@
|
||||
#include "mirage_util.slang"
|
||||
|
||||
struct ParamBuffer
|
||||
{
|
||||
matrix transform;
|
||||
};
|
||||
ParameterBlock<ParamBuffer> param_buffer : register(b1);
|
||||
|
||||
struct PSInput {
|
||||
float4 position : SV_POSITION; // 裁剪空间坐标
|
||||
float4 color : COLOR; // 颜色
|
||||
float2 lineWidth : TEXCOORD0; // 线段宽度
|
||||
float2 uv : TEXCOORD1; // 纹理坐标
|
||||
};
|
||||
|
||||
[shader("vertex")]
|
||||
PSInput vertex_main(VSInput input)
|
||||
{
|
||||
PSInput output;
|
||||
output.position = mul(float4(input.position, 0, 1.0), param_buffer.transform);
|
||||
output.color = input.color;
|
||||
output.lineWidth = input.param_a.xy;
|
||||
output.uv = input.uv;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("pixel")]
|
||||
float4 pixel_main(PSInput input) : SV_TARGET
|
||||
{
|
||||
// 计算线段宽度和矩形大小
|
||||
float2 lineWidth = input.lineWidth;
|
||||
float2 uv = input.uv;
|
||||
|
||||
bool left = uv.x > lineWidth.x;
|
||||
bool right = uv.x < 1 - lineWidth.x;
|
||||
bool top = uv.y > lineWidth.y;
|
||||
bool bottom = uv.y < 1 - lineWidth.y;
|
||||
|
||||
// 如果像素在矩形内部区域(同时在所有边界内),则丢弃它
|
||||
if (left && right && top && bottom)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
return input.color;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
#include "mirage_util.slang"
|
||||
|
||||
struct ParamBuffer
|
||||
{
|
||||
matrix transform;
|
||||
};
|
||||
ParameterBlock<ParamBuffer> param_buffer : register(b1);
|
||||
|
||||
struct PSInput {
|
||||
float4 position : SV_POSITION; // 裁剪空间坐标
|
||||
float4 color : COLOR; // 颜色
|
||||
};
|
||||
|
||||
[shader("vertex")]
|
||||
PSInput vertex_main(VSInput input)
|
||||
{
|
||||
PSInput output;
|
||||
output.position = mul(float4(input.position, 0, 1.0), param_buffer.transform);
|
||||
output.color = input.color;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("pixel")]
|
||||
float4 pixel_main(PSInput input) : SV_TARGET
|
||||
{
|
||||
return input.color;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user