圆角矩形
This commit is contained in:
parent
755fe590a1
commit
242cdacf2b
@ -59,12 +59,14 @@ if (NOT DEFINED SHADER_OUTPUT_DIR)
|
|||||||
set(SHADER_OUTPUT_DIR ${CMAKE_BINARY_DIR}/shaders CACHE PATH "Output directory for compiled shaders")
|
set(SHADER_OUTPUT_DIR ${CMAKE_BINARY_DIR}/shaders CACHE PATH "Output directory for compiled shaders")
|
||||||
message(STATUS "SHADER_OUTPUT_DIR not defined, using default: ${SHADER_OUTPUT_DIR}")
|
message(STATUS "SHADER_OUTPUT_DIR not defined, using default: ${SHADER_OUTPUT_DIR}")
|
||||||
endif ()
|
endif ()
|
||||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rect.slang" "vertex" "vertex_main")
|
function(compile_aorii_shader SHADER_FILE)
|
||||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rect.slang" "pixel" "pixel_main")
|
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/${SHADER_FILE}.slang" "vertex" "vertex_main")
|
||||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rounded_rect.slang" "vertex" "vertex_main")
|
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/${SHADER_FILE}.slang" "pixel" "pixel_main")
|
||||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rounded_rect.slang" "pixel" "pixel_main")
|
endfunction()
|
||||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_texture.slang" "vertex" "vertex_main")
|
compile_aorii_shader(aorii_rect)
|
||||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_texture.slang" "pixel" "pixel_main")
|
compile_aorii_shader(aorii_rounded_rect)
|
||||||
|
compile_aorii_shader(aorii_texture)
|
||||||
|
compile_aorii_shader(aorii_segment)
|
||||||
add_compile_shaders_target("compile_aorii_shaders" ${PROJECT_NAME})
|
add_compile_shaders_target("compile_aorii_shaders" ${PROJECT_NAME})
|
||||||
|
|
||||||
# 如果需要编译example, 添加自定义命令用于拷贝shader文件
|
# 如果需要编译example, 添加自定义命令用于拷贝shader文件
|
||||||
|
@ -34,6 +34,7 @@ bool dx_renderer::init() {
|
|||||||
rect_p.init();
|
rect_p.init();
|
||||||
rounded_rect_p.init();
|
rounded_rect_p.init();
|
||||||
texture_p.init();
|
texture_p.init();
|
||||||
|
segment_p.init();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -59,6 +60,29 @@ renderer_texture* dx_renderer::create_texture(const Eigen::Vector2i& size, textu
|
|||||||
return new dx_texture(size, in_format);
|
return new dx_texture(size, in_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Eigen::Matrix4f dx_renderer::make_projection_matrix(const Eigen::Vector2i& size) {
|
||||||
|
// 创建一个单位矩阵
|
||||||
|
Eigen::Matrix4f matrix = Eigen::Matrix4f::Identity();
|
||||||
|
|
||||||
|
// 缩放因子
|
||||||
|
const float scale_x = 2.0f / static_cast<float>(size.x());
|
||||||
|
const float scale_y = -2.0f / static_cast<float>(size.y()); // Y轴翻转,因为窗口坐标系Y轴向下
|
||||||
|
|
||||||
|
// 平移因子
|
||||||
|
constexpr float translate_x = -1.0f;
|
||||||
|
constexpr float translate_y = 1.0f;
|
||||||
|
|
||||||
|
// 设置缩放
|
||||||
|
matrix(0, 0) = scale_x;
|
||||||
|
matrix(1, 1) = scale_y;
|
||||||
|
|
||||||
|
// 设置平移
|
||||||
|
matrix(0, 3) = translate_x;
|
||||||
|
matrix(1, 3) = translate_y;
|
||||||
|
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<char> dx_renderer::load_shader(const std::string& shader_name) {
|
std::vector<char> dx_renderer::load_shader(const std::string& shader_name) {
|
||||||
auto file_pathname = aorii::get_shader_path(shader_name).generic_string() + ".dxbc";
|
auto file_pathname = aorii::get_shader_path(shader_name).generic_string() + ".dxbc";
|
||||||
std::ifstream file(file_pathname, std::ios::binary);
|
std::ifstream file(file_pathname, std::ios::binary);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "core/renderer/renderer.h"
|
#include "core/renderer/renderer.h"
|
||||||
#include "pipeline/dx_rect_pipeline.h"
|
#include "pipeline/dx_rect_pipeline.h"
|
||||||
#include "pipeline/dx_rounded_rect_pipeline.h"
|
#include "pipeline/dx_rounded_rect_pipeline.h"
|
||||||
|
#include "pipeline/dx_segment_pipeline.h"
|
||||||
#include "pipeline/dx_texture_pipeline.h"
|
#include "pipeline/dx_texture_pipeline.h"
|
||||||
|
|
||||||
class dx_window;
|
class dx_window;
|
||||||
@ -22,6 +23,10 @@ public:
|
|||||||
rect_pipeline* get_rect_pipeline() override { return &rect_p; }
|
rect_pipeline* get_rect_pipeline() override { return &rect_p; }
|
||||||
rounded_rect_pipeline* get_rounded_rect_pipeline() override { return &rounded_rect_p; }
|
rounded_rect_pipeline* get_rounded_rect_pipeline() override { return &rounded_rect_p; }
|
||||||
texture_pipeline* get_texture_pipeline() override { return &texture_p; }
|
texture_pipeline* get_texture_pipeline() override { return &texture_p; }
|
||||||
|
segment_pipeline* get_segment_pipeline() override { return &segment_p; }
|
||||||
|
|
||||||
|
Eigen::Matrix4f make_projection_matrix(const Eigen::Vector2i& size) override;
|
||||||
|
|
||||||
[[nodiscard]] ID3D11BlendState* get_blend_state() const { return blend_state; }
|
[[nodiscard]] ID3D11BlendState* get_blend_state() const { return blend_state; }
|
||||||
|
|
||||||
std::vector<char> load_shader(const std::string& shader_name) override;
|
std::vector<char> load_shader(const std::string& shader_name) override;
|
||||||
@ -39,6 +44,7 @@ private:
|
|||||||
dx_rect_pipeline rect_p;
|
dx_rect_pipeline rect_p;
|
||||||
dx_rounded_rect_pipeline rounded_rect_p;
|
dx_rounded_rect_pipeline rounded_rect_p;
|
||||||
dx_texture_pipeline texture_p;
|
dx_texture_pipeline texture_p;
|
||||||
|
dx_segment_pipeline segment_p;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline DXGI_FORMAT get_dxgi_format(texture_format format) {
|
inline DXGI_FORMAT get_dxgi_format(texture_format format) {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
using namespace aorii;
|
using namespace aorii;
|
||||||
|
|
||||||
|
static float thickness = 1.f;
|
||||||
bool dx_window::create_surface(GLFWwindow* in_window) {
|
bool dx_window::create_surface(GLFWwindow* in_window) {
|
||||||
auto dx = aorii::get_renderer<dx_renderer>();
|
auto dx = aorii::get_renderer<dx_renderer>();
|
||||||
const auto d3d_device = dx->get_d3d_device();
|
const auto d3d_device = dx->get_d3d_device();
|
||||||
@ -69,6 +70,9 @@ bool dx_window::create_surface(GLFWwindow* in_window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test_texture = dx->load_image(R"(D:\69054578_p0.jpg)", texture_format::RGBA8_UNORM);
|
test_texture = dx->load_image(R"(D:\69054578_p0.jpg)", texture_format::RGBA8_UNORM);
|
||||||
|
glfwSetScrollCallback(get_glfw_window(), [](GLFWwindow* window, double xoffset, double yoffset) {
|
||||||
|
thickness += yoffset;
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,16 +84,19 @@ void dx_window::begin_frame() {
|
|||||||
d3d_context->OMSetRenderTargets(1, &render_target_view, nullptr);
|
d3d_context->OMSetRenderTargets(1, &render_target_view, nullptr);
|
||||||
d3d_context->OMSetBlendState(render->get_blend_state(), nullptr, 0xffffffff);
|
d3d_context->OMSetBlendState(render->get_blend_state(), nullptr, 0xffffffff);
|
||||||
d3d_context->ClearRenderTargetView(render_target_view, clear_color);
|
d3d_context->ClearRenderTargetView(render_target_view, clear_color);
|
||||||
context.set_projection_matrix(projection_matrix);
|
context.set_projection_matrix(projection_matrix, get_framebuffer_size());
|
||||||
|
|
||||||
context.draw_rectangle({ 400, 0 }, { 100, 100 }, { 0, 1, 0, 1 });
|
context.draw_rectangle({ 400, 0 }, { 100, 100 }, { 0, 1, 0, 1 });
|
||||||
auto radius = abs(sin(get_total_time().count())) * 50;
|
auto radius = abs(sin(get_total_time().count())) * 50;
|
||||||
context.draw_rounded_rectangle({ 100, 100 }, { 200, 200 }, { 1, 0, 0, 1 }, radius);
|
auto angle = sin(get_total_time().count() * 0.001) * 45;
|
||||||
|
context.draw_rounded_rectangle({ 100, 100 }, { 200, 400 }, { 1, 0, 0, 1 }, angle, 10);
|
||||||
|
|
||||||
auto height = sin(get_total_time().count()) * 100;
|
double mouse_x, mouse_y;
|
||||||
context.draw_line({ 600, 600 - height }, { 700, 600 + height }, { 0, 0, 1, 1 }, 0.5);
|
glfwGetCursorPos(get_glfw_window(), &mouse_x, &mouse_y);
|
||||||
|
// auto height = sin(get_total_time().count()) * 100;
|
||||||
|
context.draw_line( { 600, 600 }, { mouse_x, mouse_y }, { 1, 0, 1, 1 }, thickness);
|
||||||
|
|
||||||
if (test_texture) context.draw_texture({ 0, 0 }, test_texture->size(), test_texture);
|
// if (test_texture) context.draw_texture({ 0, 0 }, test_texture->size(), test_texture);
|
||||||
|
|
||||||
context.flush();
|
context.flush();
|
||||||
|
|
||||||
|
27
src/renderer/backend/dx/pipeline/dx_sdf_text_pipeline.cpp
Normal file
27
src/renderer/backend/dx/pipeline/dx_sdf_text_pipeline.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "dx_sdf_text_pipeline.h"
|
||||||
|
|
||||||
|
#include "backend/dx/dx_renderer.h"
|
||||||
|
|
||||||
|
bool dx_sdf_text_pipeline::init() {
|
||||||
|
sdf_text_pipeline::init();
|
||||||
|
loader.load("aorii_sdf_text_vertex_main", "aorii_sdf_text_pixel_main");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dx_sdf_text_pipeline::use() {
|
||||||
|
loader.use();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dx_sdf_text_pipeline::draw() {
|
||||||
|
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
|
||||||
|
|
||||||
|
// 绘制
|
||||||
|
d3d_context->DrawIndexed(index_buffer->get_size(), 0, 0);
|
||||||
|
d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dx_sdf_text_pipeline::set_param(const param& in_param) { sdf_text_pipeline::set_param(in_param); }
|
||||||
|
|
||||||
|
void dx_sdf_text_pipeline::set_sdf_font_param(const sdf_font_param& in_param) {
|
||||||
|
sdf_text_pipeline::set_sdf_font_param(in_param);
|
||||||
|
}
|
16
src/renderer/backend/dx/pipeline/dx_sdf_text_pipeline.h
Normal file
16
src/renderer/backend/dx/pipeline/dx_sdf_text_pipeline.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "dx_pipeline_loader.h"
|
||||||
|
#include "core/pipeline/sdf_text_pipeline.h"
|
||||||
|
|
||||||
|
class dx_sdf_text_pipeline : public sdf_text_pipeline {
|
||||||
|
public:
|
||||||
|
bool init() override;
|
||||||
|
|
||||||
|
void use() override;
|
||||||
|
void draw() override;
|
||||||
|
|
||||||
|
void set_param(const param& in_param) override;
|
||||||
|
void set_sdf_font_param(const sdf_font_param& in_param) override;
|
||||||
|
private:
|
||||||
|
dx_pipeline_loader loader;
|
||||||
|
};
|
34
src/renderer/backend/dx/pipeline/dx_segment_pipeline.cpp
Normal file
34
src/renderer/backend/dx/pipeline/dx_segment_pipeline.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "dx_segment_pipeline.h"
|
||||||
|
|
||||||
|
#include "backend/dx/dx_renderer.h"
|
||||||
|
|
||||||
|
bool dx_segment_pipeline::init() {
|
||||||
|
segment_pipeline::init();
|
||||||
|
loader.load("aorii_segment_vertex_main", "aorii_segment_pixel_main");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dx_segment_pipeline::use() {
|
||||||
|
loader.use();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dx_segment_pipeline::draw() {
|
||||||
|
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
|
||||||
|
|
||||||
|
// 设置顶点缓冲区
|
||||||
|
constexpr UINT stride = sizeof(aorii_vertex);
|
||||||
|
constexpr UINT offset = 0;
|
||||||
|
auto* v_buffer = static_cast<ID3D11Buffer*>(vertex_buffer->get_native_handle());
|
||||||
|
auto* i_buffer = static_cast<ID3D11Buffer*>(index_buffer->get_native_handle());
|
||||||
|
auto* c_buffer = static_cast<ID3D11Buffer*>(param_buffer->get_native_handle());
|
||||||
|
d3d_context->IASetVertexBuffers(0, 1, &v_buffer, &stride, &offset);
|
||||||
|
d3d_context->IASetIndexBuffer(i_buffer, DXGI_FORMAT_R32_UINT, 0);
|
||||||
|
d3d_context->VSSetConstantBuffers(0, 1, &c_buffer);
|
||||||
|
d3d_context->PSSetConstantBuffers(0, 1, &c_buffer);
|
||||||
|
|
||||||
|
// 设置图元拓扑
|
||||||
|
d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||||
|
|
||||||
|
// 绘制矩形
|
||||||
|
d3d_context->Draw(vertex_buffer->get_size(), 0);
|
||||||
|
}
|
12
src/renderer/backend/dx/pipeline/dx_segment_pipeline.h
Normal file
12
src/renderer/backend/dx/pipeline/dx_segment_pipeline.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "dx_pipeline_loader.h"
|
||||||
|
#include "core/pipeline/segment_pipeline.h"
|
||||||
|
|
||||||
|
class dx_segment_pipeline : public segment_pipeline {
|
||||||
|
public:
|
||||||
|
bool init() override;
|
||||||
|
void use() override;
|
||||||
|
void draw() override;
|
||||||
|
private:
|
||||||
|
dx_pipeline_loader loader;
|
||||||
|
};
|
@ -5,9 +5,10 @@ class rounded_rect_pipeline : public pipeline {
|
|||||||
public:
|
public:
|
||||||
struct param {
|
struct param {
|
||||||
Eigen::Matrix4f projection_matrix;
|
Eigen::Matrix4f projection_matrix;
|
||||||
Eigen::Vector2f pos;
|
Eigen::Vector2f p1;
|
||||||
Eigen::Vector2f size;
|
Eigen::Vector2f p2;
|
||||||
float radius;
|
float radius;
|
||||||
|
float thickness;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool init() override;
|
bool init() override;
|
||||||
|
22
src/renderer/core/pipeline/sdf_text_pipeline.cpp
Normal file
22
src/renderer/core/pipeline/sdf_text_pipeline.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "sdf_text_pipeline.h"
|
||||||
|
|
||||||
|
#include "core/renderer/renderer.h"
|
||||||
|
|
||||||
|
bool sdf_text_pipeline::init() {
|
||||||
|
param_buffer = aorii::get_renderer_raw()->create_buffer(buffer_type::constant, sizeof(param), 1);
|
||||||
|
sdf_font_param_buffer = aorii::get_renderer_raw()->create_buffer(buffer_type::constant, sizeof(sdf_font_param), 1);
|
||||||
|
return pipeline::init();
|
||||||
|
}
|
||||||
|
void sdf_text_pipeline::destroy() {
|
||||||
|
pipeline::destroy();
|
||||||
|
aorii::get_renderer_raw()->destroy_buffer(param_buffer);
|
||||||
|
aorii::get_renderer_raw()->destroy_buffer(sdf_font_param_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdf_text_pipeline::set_param(const param& in_param) {
|
||||||
|
param_buffer->set_data(in_param);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdf_text_pipeline::set_sdf_font_param(const sdf_font_param& in_param) {
|
||||||
|
sdf_font_param_buffer->set_data(in_param);
|
||||||
|
}
|
28
src/renderer/core/pipeline/sdf_text_pipeline.h
Normal file
28
src/renderer/core/pipeline/sdf_text_pipeline.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cfloat>
|
||||||
|
|
||||||
|
#include "pipeline.h"
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include <omp.h>
|
||||||
|
|
||||||
|
class sdf_text_pipeline : public pipeline {
|
||||||
|
public:
|
||||||
|
struct param {
|
||||||
|
Eigen::Matrix4f projection_matrix;
|
||||||
|
}; // b0
|
||||||
|
struct sdf_font_param {
|
||||||
|
float smoothing;
|
||||||
|
float thickness;
|
||||||
|
float outline_width;
|
||||||
|
linear_color outline_color;
|
||||||
|
}; // b1
|
||||||
|
bool init() override;
|
||||||
|
void destroy() override;
|
||||||
|
|
||||||
|
virtual void set_param(const param& in_param);
|
||||||
|
virtual void set_sdf_font_param(const sdf_font_param& in_param);
|
||||||
|
private:
|
||||||
|
renderer_buffer* param_buffer = nullptr;
|
||||||
|
renderer_buffer* sdf_font_param_buffer = nullptr;
|
||||||
|
};
|
17
src/renderer/core/pipeline/segment_pipeline.cpp
Normal file
17
src/renderer/core/pipeline/segment_pipeline.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "segment_pipeline.h"
|
||||||
|
|
||||||
|
#include "core/renderer/renderer.h"
|
||||||
|
|
||||||
|
bool segment_pipeline::init() {
|
||||||
|
pipeline::init();
|
||||||
|
param_buffer = aorii::get_renderer_raw()->create_buffer(buffer_type::constant, sizeof(param), 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void segment_pipeline::destroy() {
|
||||||
|
aorii::get_renderer_raw()->destroy_buffer(param_buffer);
|
||||||
|
pipeline::destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void segment_pipeline::set_param(const param& in_param) {
|
||||||
|
param_buffer->set_data(in_param);
|
||||||
|
}
|
19
src/renderer/core/pipeline/segment_pipeline.h
Normal file
19
src/renderer/core/pipeline/segment_pipeline.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pipeline.h"
|
||||||
|
|
||||||
|
class segment_pipeline : public pipeline {
|
||||||
|
public:
|
||||||
|
struct param {
|
||||||
|
Eigen::Matrix4f projection_matrix;
|
||||||
|
Eigen::Vector2f point_a;
|
||||||
|
Eigen::Vector2f point_b;
|
||||||
|
float thickness;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool init() override;
|
||||||
|
void destroy() override;
|
||||||
|
|
||||||
|
void set_param(const param& in_param);
|
||||||
|
protected:
|
||||||
|
renderer_buffer* param_buffer = nullptr;
|
||||||
|
};
|
@ -6,6 +6,7 @@
|
|||||||
#include "renderer_buffer.h"
|
#include "renderer_buffer.h"
|
||||||
#include "core/pipeline/pipeline.h"
|
#include "core/pipeline/pipeline.h"
|
||||||
|
|
||||||
|
class segment_pipeline;
|
||||||
class texture_pipeline;
|
class texture_pipeline;
|
||||||
class rounded_rect_pipeline;
|
class rounded_rect_pipeline;
|
||||||
class rect_pipeline;
|
class rect_pipeline;
|
||||||
@ -241,6 +242,9 @@ public:
|
|||||||
virtual rect_pipeline* get_rect_pipeline() = 0;
|
virtual rect_pipeline* get_rect_pipeline() = 0;
|
||||||
virtual rounded_rect_pipeline* get_rounded_rect_pipeline() = 0;
|
virtual rounded_rect_pipeline* get_rounded_rect_pipeline() = 0;
|
||||||
virtual texture_pipeline* get_texture_pipeline() = 0;
|
virtual texture_pipeline* get_texture_pipeline() = 0;
|
||||||
|
virtual segment_pipeline* get_segment_pipeline() = 0;
|
||||||
|
|
||||||
|
virtual Eigen::Matrix4f make_projection_matrix(const Eigen::Vector2i& size) = 0;
|
||||||
private:
|
private:
|
||||||
virtual renderer_window* create_window() = 0;
|
virtual renderer_window* create_window() = 0;
|
||||||
virtual void destroy_window(renderer_window* window);
|
virtual void destroy_window(renderer_window* window);
|
||||||
|
@ -6,54 +6,34 @@
|
|||||||
void renderer_context::init() {
|
void renderer_context::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_context::draw_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color) {
|
void renderer_context::draw_rectangle(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, const linear_color& in_color) {
|
||||||
to_rect_pipeline();
|
to_rect_pipeline();
|
||||||
make_rect(in_pos, in_size, in_color);
|
make_rect(in_pos, in_size, in_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_context::draw_rounded_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color, float in_radius) {
|
void renderer_context::draw_rounded_rectangle(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, const linear_color& in_color, float in_angle, float in_radius) {
|
||||||
to_rounded_rect_pipeline(in_pos, in_size, in_radius);
|
to_rounded_rect_pipeline(in_pos, in_size, in_angle, in_radius);
|
||||||
make_rect(in_pos, in_size, in_color);
|
|
||||||
|
make_rect(in_pos, in_size, in_color, in_angle);
|
||||||
// 立刻绘制并重置管线, 因为下一个绘制命令的参数可能不同, 所以无法合批
|
// 立刻绘制并重置管线, 因为下一个绘制命令的参数可能不同, 所以无法合批
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_context::draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen::Vector2i& in_pos_p2, const linear_color& in_color, float in_thickness) {
|
void renderer_context::draw_line(const Eigen::Vector2f& in_pos_p1, const Eigen::Vector2f& in_pos_p2, const linear_color& in_color, float in_thickness) {
|
||||||
to_rect_pipeline();
|
|
||||||
const Eigen::Vector2f direction = (in_pos_p2 - in_pos_p1).cast<float>().normalized();
|
|
||||||
const Eigen::Vector2f normal = { -direction.y(), direction.x() };
|
|
||||||
const Eigen::Vector2f offset = normal * in_thickness;
|
|
||||||
|
|
||||||
const aorii_vertex v1{ { in_pos_p1.x() + offset.x(), in_pos_p1.y() + offset.y() }, { 0, 0 }, in_color };
|
|
||||||
const aorii_vertex v2{ { in_pos_p1.x() - offset.x(), in_pos_p1.y() - offset.y() }, { 1, 0 }, in_color };
|
|
||||||
const aorii_vertex v3{ { in_pos_p2.x() + offset.x(), in_pos_p2.y() + offset.y() }, { 0, 1 }, in_color };
|
|
||||||
const aorii_vertex v4{ { in_pos_p2.x() - offset.x(), in_pos_p2.y() - offset.y() }, { 1, 1 }, in_color };
|
|
||||||
|
|
||||||
const uint32_t index1 = vertices.size();
|
|
||||||
vertices.push_back(v1);
|
|
||||||
const uint32_t index2 = vertices.size();
|
|
||||||
vertices.push_back(v2);
|
|
||||||
const uint32_t index3 = vertices.size();
|
|
||||||
vertices.push_back(v3);
|
|
||||||
const uint32_t index4 = vertices.size();
|
|
||||||
vertices.push_back(v4);
|
|
||||||
|
|
||||||
const aorii_triangle t1 = { index1, index2, index3 };
|
|
||||||
const aorii_triangle t2 = { index2, index3, index4 };
|
|
||||||
triangles.push_back(t1);
|
|
||||||
triangles.push_back(t2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_context::draw_texture(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size,
|
void renderer_context::draw_texture(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size,
|
||||||
renderer_texture* in_texture, const linear_color& in_color) {
|
renderer_texture* in_texture, const linear_color& in_color) {
|
||||||
to_texture_pipeline(in_texture);
|
to_texture_pipeline(in_texture);
|
||||||
make_rect(in_pos, in_size, in_color);
|
make_rect(in_pos, in_size, in_color);
|
||||||
// 立刻绘制并重置管线, 因为下一个绘制命令的参数可能不同, 所以无法合批
|
// 立刻绘制并重置管线, 因为下一个绘制命令的参数可能不同, 所以无法合批
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_context::set_projection_matrix(const Eigen::Matrix4f& in_matrix) {
|
void renderer_context::set_projection_matrix(const Eigen::Matrix4f& in_matrix, const Eigen::Vector2i& in_framebuffer_size) {
|
||||||
projection_matrix = in_matrix;
|
projection_matrix = in_matrix;
|
||||||
|
framebuffer_size = in_framebuffer_size;
|
||||||
|
|
||||||
// 更新默认管线的投影矩阵
|
// 更新默认管线的投影矩阵
|
||||||
const auto rect_p = aorii::get_renderer<dx_renderer>()->get_rect_pipeline();
|
const auto rect_p = aorii::get_renderer<dx_renderer>()->get_rect_pipeline();
|
||||||
@ -63,6 +43,7 @@ void renderer_context::set_projection_matrix(const Eigen::Matrix4f& in_matrix) {
|
|||||||
texture_p->set_param({ in_matrix });
|
texture_p->set_param({ in_matrix });
|
||||||
|
|
||||||
// 圆角矩形管线的投影矩阵不需要更新, 因为它在每次绘制时都会更新
|
// 圆角矩形管线的投影矩阵不需要更新, 因为它在每次绘制时都会更新
|
||||||
|
// 线段管线的投影矩阵不需要更新, 因为它在每次绘制时都会更新
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_context::to_rect_pipeline() {
|
void renderer_context::to_rect_pipeline() {
|
||||||
@ -70,14 +51,32 @@ void renderer_context::to_rect_pipeline() {
|
|||||||
switch_pipeline(rect_p);
|
switch_pipeline(rect_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_context::to_rounded_rect_pipeline(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, float in_radius) {
|
void renderer_context::to_rounded_rect_pipeline(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, float in_angle, float in_radius) {
|
||||||
const auto rounded_rect_p = aorii::get_renderer<dx_renderer>()->get_rounded_rect_pipeline();
|
const auto rounded_rect_p = aorii::get_renderer<dx_renderer>()->get_rounded_rect_pipeline();
|
||||||
switch_pipeline(rounded_rect_p);
|
switch_pipeline(rounded_rect_p);
|
||||||
|
|
||||||
|
Eigen::Vector2f top_middle = in_pos + Eigen::Vector2f(in_size.x() / 2, 0);
|
||||||
|
Eigen::Vector2f bottom_middle = in_pos + Eigen::Vector2f(in_size.x() / 2, in_size.y());
|
||||||
|
|
||||||
|
// 如果角度不为0, 则需要计算旋转后的坐标
|
||||||
|
if (in_angle != 0) {
|
||||||
|
// 将top_middle和bottom_middle绕盒子中心旋转
|
||||||
|
const Eigen::Vector2f& center = in_pos + in_size / 2;
|
||||||
|
Eigen::Affine2f transform =
|
||||||
|
Eigen::Translation<float, 2>(center) * // 平移到旋转中心
|
||||||
|
Eigen::Rotation2D<float>(in_angle) * // 旋转
|
||||||
|
Eigen::Translation<float, 2>(-center); // 平移回原点
|
||||||
|
|
||||||
|
top_middle = transform * top_middle;
|
||||||
|
bottom_middle = transform * bottom_middle;
|
||||||
|
}
|
||||||
|
|
||||||
rounded_rect_pipeline::param param;
|
rounded_rect_pipeline::param param;
|
||||||
param.projection_matrix = projection_matrix;
|
param.projection_matrix = projection_matrix;
|
||||||
param.pos = in_pos.cast<float>();
|
param.p1 = top_middle;
|
||||||
param.size = in_size.cast<float>();
|
param.p2 = bottom_middle;
|
||||||
param.radius = in_radius;
|
param.radius = in_radius;
|
||||||
|
param.thickness = in_size.x();
|
||||||
rounded_rect_p->set_param(param);
|
rounded_rect_p->set_param(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,24 +86,72 @@ void renderer_context::to_texture_pipeline(renderer_texture* in_texture) {
|
|||||||
texture_p->set_texture(in_texture);
|
texture_p->set_texture(in_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_context::make_rect(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size,
|
void renderer_context::to_segment_pipeline(const Eigen::Vector2f& in_pos_p1, const Eigen::Vector2f& in_pos_p2, float in_thickness) {
|
||||||
const linear_color& in_color) {
|
const auto segment_p = aorii::get_renderer<dx_renderer>()->get_segment_pipeline();
|
||||||
const aorii_vertex v1{ { in_pos.x(), in_pos.y() }, { 0, 0 }, in_color }; // 左上角
|
switch_pipeline(segment_p);
|
||||||
const aorii_vertex v2{ { in_pos.x() + in_size.x(), in_pos.y() }, { 1, 0 }, in_color }; // 右上角
|
|
||||||
const aorii_vertex v3{ { in_pos.x(), in_pos.y() + in_size.y() }, { 0, 1 }, in_color }; // 左下角
|
|
||||||
const aorii_vertex v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, { 1, 1 }, in_color }; // 右下角
|
|
||||||
|
|
||||||
const uint32_t index1 = vertices.size();
|
segment_pipeline::param param;
|
||||||
vertices.push_back(v1);
|
param.projection_matrix = projection_matrix;
|
||||||
const uint32_t index2 = vertices.size();
|
param.point_a = in_pos_p1;
|
||||||
vertices.push_back(v2);
|
param.point_b = in_pos_p2;
|
||||||
const uint32_t index3 = vertices.size();
|
param.thickness = in_thickness;
|
||||||
vertices.push_back(v3);
|
segment_p->set_param(param);
|
||||||
const uint32_t index4 = vertices.size();
|
}
|
||||||
vertices.push_back(v4);
|
|
||||||
|
void renderer_context::make_rect(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size,
|
||||||
const aorii_triangle t1 = { index1, index2, index3 };
|
const linear_color& in_color, float in_angle) {
|
||||||
const aorii_triangle t2 = { index2, index3, index4 };
|
// 如果角度不为0, 则需要计算旋转后的坐标
|
||||||
triangles.push_back(t1);
|
if (in_angle != 0) {
|
||||||
triangles.push_back(t2);
|
// 绕盒子中心旋转
|
||||||
|
// 创建仿射变换矩阵(先平移,后旋转,再平移回去)
|
||||||
|
const Eigen::Vector2f& center = in_pos + in_size / 2;
|
||||||
|
Eigen::Affine2f transform =
|
||||||
|
Eigen::Translation<float, 2>(center) * // 平移到旋转中心
|
||||||
|
Eigen::Rotation2D<float>(in_angle) * // 旋转
|
||||||
|
Eigen::Translation<float, 2>(-center); // 平移回原点
|
||||||
|
|
||||||
|
const Eigen::Vector2f top_left = transform * in_pos;
|
||||||
|
const Eigen::Vector2f top_right = transform * Eigen::Vector2f(in_pos.x() + in_size.x(), in_pos.y());
|
||||||
|
const Eigen::Vector2f bottom_left = transform * Eigen::Vector2f(in_pos.x(), in_pos.y() + in_size.y());
|
||||||
|
const Eigen::Vector2f bottom_right = transform * (in_pos + in_size);
|
||||||
|
|
||||||
|
const aorii_vertex v1{ { top_left.x(), top_left.y() }, { 0, 0 }, in_color }; // 左上角
|
||||||
|
const aorii_vertex v2{ { top_right.x(), top_right.y() }, { 1, 0 }, in_color }; // 右上角
|
||||||
|
const aorii_vertex v3{ { bottom_left.x(), bottom_left.y() }, { 0, 1 }, in_color }; // 左下角
|
||||||
|
const aorii_vertex v4{ { bottom_right.x(), bottom_right.y() }, { 1, 1 }, in_color }; // 右下角
|
||||||
|
|
||||||
|
const uint32_t index1 = vertices.size();
|
||||||
|
vertices.push_back(v1);
|
||||||
|
const uint32_t index2 = vertices.size();
|
||||||
|
vertices.push_back(v2);
|
||||||
|
const uint32_t index3 = vertices.size();
|
||||||
|
vertices.push_back(v3);
|
||||||
|
const uint32_t index4 = vertices.size();
|
||||||
|
vertices.push_back(v4);
|
||||||
|
|
||||||
|
const aorii_triangle t1 = { index1, index2, index3 };
|
||||||
|
const aorii_triangle t2 = { index2, index3, index4 };
|
||||||
|
triangles.push_back(t1);
|
||||||
|
triangles.push_back(t2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const aorii_vertex v1{ { in_pos.x(), in_pos.y() }, { 0, 0 }, in_color }; // 左上角
|
||||||
|
const aorii_vertex v2{ { in_pos.x() + in_size.x(), in_pos.y() }, { 1, 0 }, in_color }; // 右上角
|
||||||
|
const aorii_vertex v3{ { in_pos.x(), in_pos.y() + in_size.y() }, { 0, 1 }, in_color }; // 左下角
|
||||||
|
const aorii_vertex v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, { 1, 1 }, in_color }; // 右下角
|
||||||
|
|
||||||
|
const uint32_t index1 = vertices.size();
|
||||||
|
vertices.push_back(v1);
|
||||||
|
const uint32_t index2 = vertices.size();
|
||||||
|
vertices.push_back(v2);
|
||||||
|
const uint32_t index3 = vertices.size();
|
||||||
|
vertices.push_back(v3);
|
||||||
|
const uint32_t index4 = vertices.size();
|
||||||
|
vertices.push_back(v4);
|
||||||
|
|
||||||
|
const aorii_triangle t1 = { index1, index2, index3 };
|
||||||
|
const aorii_triangle t2 = { index2, index3, index4 };
|
||||||
|
triangles.push_back(t1);
|
||||||
|
triangles.push_back(t2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,16 +16,17 @@ public:
|
|||||||
* @param in_size 绘制的大小(受控件缩放影响)
|
* @param in_size 绘制的大小(受控件缩放影响)
|
||||||
* @param in_color 绘制的颜色
|
* @param in_color 绘制的颜色
|
||||||
*/
|
*/
|
||||||
void draw_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color);
|
void draw_rectangle(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, const linear_color& in_color);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绘制一个实心圆角矩形
|
* 绘制一个实心圆角矩形
|
||||||
* @param in_pos 当前控件坐标系的位置
|
* @param in_pos 当前控件坐标系的位置
|
||||||
* @param in_size 绘制的大小(受控件缩放影响)
|
* @param in_size 绘制的大小(受控件缩放影响)
|
||||||
* @param in_color 绘制的颜色
|
* @param in_color 绘制的颜色
|
||||||
|
* @param in_angle
|
||||||
* @param in_radius 圆角半径(像素)
|
* @param in_radius 圆角半径(像素)
|
||||||
*/
|
*/
|
||||||
void draw_rounded_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color, float in_radius);
|
void draw_rounded_rectangle(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, const linear_color& in_color, float in_angle, float in_radius);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绘制一条线
|
* 绘制一条线
|
||||||
@ -34,7 +35,7 @@ public:
|
|||||||
* @param in_color 线颜色
|
* @param in_color 线颜色
|
||||||
* @param in_thickness 线宽度(像素), 当宽度为0时, 按照最小线宽度绘制
|
* @param in_thickness 线宽度(像素), 当宽度为0时, 按照最小线宽度绘制
|
||||||
*/
|
*/
|
||||||
void draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen::Vector2i& in_pos_p2, const linear_color& in_color, float in_thickness);
|
void draw_line(const Eigen::Vector2f& in_pos_p1, const Eigen::Vector2f& in_pos_p2, const linear_color& in_color, float in_thickness);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绘制一个纹理
|
* 绘制一个纹理
|
||||||
@ -42,7 +43,7 @@ public:
|
|||||||
* @param in_size 绘制的大小(受控件缩放影响)
|
* @param in_size 绘制的大小(受控件缩放影响)
|
||||||
* @param in_texture 纹理
|
* @param in_texture 纹理
|
||||||
*/
|
*/
|
||||||
void draw_texture(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, renderer_texture* in_texture, const linear_color& in_color = linear_color::white);
|
void draw_texture(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, renderer_texture* in_texture, const linear_color& in_color = linear_color::white);
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
@ -63,7 +64,7 @@ public:
|
|||||||
}
|
}
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
void set_projection_matrix(const Eigen::Matrix4f& in_matrix);
|
void set_projection_matrix(const Eigen::Matrix4f& in_matrix, const Eigen::Vector2i& in_framebuffer_size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void switch_pipeline(pipeline* in_pipeline) {
|
void switch_pipeline(pipeline* in_pipeline) {
|
||||||
@ -79,14 +80,16 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void to_rect_pipeline();
|
void to_rect_pipeline();
|
||||||
void to_rounded_rect_pipeline(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, float in_radius);
|
void to_rounded_rect_pipeline(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, float in_angle, float in_radius);
|
||||||
void to_texture_pipeline(renderer_texture* in_texture);
|
void to_texture_pipeline(renderer_texture* in_texture);
|
||||||
|
void to_segment_pipeline(const Eigen::Vector2f& in_pos_p1, const Eigen::Vector2f& in_pos_p2, float in_thickness);
|
||||||
private:
|
private:
|
||||||
std::vector<aorii_vertex> vertices;
|
std::vector<aorii_vertex> vertices;
|
||||||
std::vector<aorii_triangle> triangles;
|
std::vector<aorii_triangle> triangles;
|
||||||
|
|
||||||
pipeline* current_pipeline = nullptr;
|
pipeline* current_pipeline = nullptr;
|
||||||
Eigen::Matrix4f projection_matrix;
|
Eigen::Matrix4f projection_matrix;
|
||||||
|
Eigen::Vector2i framebuffer_size;
|
||||||
private:
|
private:
|
||||||
void make_rect(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color);
|
void make_rect(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, const linear_color& in_color, float in_angle = 0);
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include "renderer_window.h"
|
#include "renderer_window.h"
|
||||||
|
|
||||||
|
#include "core/renderer/renderer.h"
|
||||||
#include "GLFW/glfw3native.h"
|
#include "GLFW/glfw3native.h"
|
||||||
|
|
||||||
renderer_window::~renderer_window() { if (window) glfwDestroyWindow(window); }
|
renderer_window::~renderer_window() { if (window) glfwDestroyWindow(window); }
|
||||||
@ -10,27 +12,7 @@ bool renderer_window::init(const Eigen::Vector2i& in_size, const std::string& in
|
|||||||
}
|
}
|
||||||
|
|
||||||
Eigen::Matrix4f renderer_window::get_projection_matrix() const {
|
Eigen::Matrix4f renderer_window::get_projection_matrix() const {
|
||||||
// 创建一个单位矩阵
|
return aorii::get_renderer_raw()->make_projection_matrix(get_window_size());
|
||||||
Eigen::Matrix4f matrix = Eigen::Matrix4f::Identity();
|
|
||||||
const auto& window_size = get_window_size();
|
|
||||||
|
|
||||||
// 缩放因子
|
|
||||||
const float scale_x = 2.0f / static_cast<float>(window_size.x());
|
|
||||||
const float scale_y = -2.0f / static_cast<float>(window_size.y()); // Y轴翻转,因为窗口坐标系Y轴向下
|
|
||||||
|
|
||||||
// 平移因子
|
|
||||||
constexpr float translate_x = -1.0f;
|
|
||||||
constexpr float translate_y = 1.0f;
|
|
||||||
|
|
||||||
// 设置缩放
|
|
||||||
matrix(0, 0) = scale_x;
|
|
||||||
matrix(1, 1) = scale_y;
|
|
||||||
|
|
||||||
// 设置平移
|
|
||||||
matrix(0, 3) = translate_x;
|
|
||||||
matrix(1, 3) = translate_y;
|
|
||||||
|
|
||||||
return matrix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* renderer_window::get_window_handle() const {
|
void* renderer_window::get_window_handle() const {
|
||||||
|
@ -30,7 +30,7 @@ public:
|
|||||||
glfwGetFramebufferSize(window, &w, &h);
|
glfwGetFramebufferSize(window, &w, &h);
|
||||||
return { w, h };
|
return { w, h };
|
||||||
}
|
}
|
||||||
[[nodiscard]] virtual Eigen::Matrix4f get_projection_matrix() const;
|
[[nodiscard]] Eigen::Matrix4f get_projection_matrix() const;
|
||||||
|
|
||||||
[[nodiscard]] void* get_window_handle() const;
|
[[nodiscard]] void* get_window_handle() const;
|
||||||
[[nodiscard]] GLFWwindow* get_glfw_window() const { return window; }
|
[[nodiscard]] GLFWwindow* get_glfw_window() const { return window; }
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
struct ParamBuffer
|
cbuffer ParamBuffer : register(b0)
|
||||||
{
|
{
|
||||||
matrix transform;
|
matrix transform;
|
||||||
float2 pos; // 屏幕坐标
|
float2 p1; // 点1位置
|
||||||
float2 size; // 圆角矩形像素单位大小
|
float2 p2; // 点2位置
|
||||||
float radius; // 圆角像素单位
|
float radius; // 圆角像素单位
|
||||||
|
float thickness; // 线段的宽度
|
||||||
};
|
};
|
||||||
ParameterBlock<ParamBuffer> param_buffer : register(b0);
|
|
||||||
|
|
||||||
struct VSInput {
|
struct VSInput {
|
||||||
float2 position : POSITION; // 窗口坐标
|
float2 position : POSITION; // 窗口坐标
|
||||||
@ -22,7 +22,8 @@ struct PSInput {
|
|||||||
PSInput vertex_main(VSInput input)
|
PSInput vertex_main(VSInput input)
|
||||||
{
|
{
|
||||||
PSInput output;
|
PSInput output;
|
||||||
output.position = mul(float4(input.position, 0.0, 1.0), param_buffer.transform);
|
output.position = mul(float4(input.position, 0.0, 1.0), transform);
|
||||||
|
output.uv = input.uv;
|
||||||
output.color = input.color;
|
output.color = input.color;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@ -30,24 +31,30 @@ PSInput vertex_main(VSInput input)
|
|||||||
// 圆角矩形像素着色器
|
// 圆角矩形像素着色器
|
||||||
float4 pixel_main(PSInput input) : SV_TARGET
|
float4 pixel_main(PSInput input) : SV_TARGET
|
||||||
{
|
{
|
||||||
// 圆角半径
|
// 计算input.position到线段p1p2的最短距离
|
||||||
float radius = param_buffer.radius;
|
float2 p = input.uv;
|
||||||
// 计算矩形的中心位置
|
return float4(p, 0, 1);
|
||||||
float2 rect_center = param_buffer.pos + param_buffer.size * 0.5;
|
|
||||||
// 计算半尺寸,减去圆角半径
|
|
||||||
float2 half_size = param_buffer.size * 0.5 - radius;
|
|
||||||
|
|
||||||
// 当前像素在视口内位置
|
// 计算当前片段到线段的距离
|
||||||
float2 pixel_pos = input.position.xy;
|
float2 ba = p2 - p1;
|
||||||
// 将坐标系平移到矩形中心
|
float2 pa = p - p1;
|
||||||
float2 pos = pixel_pos - rect_center;
|
float2 ba_norm = normalize(ba);
|
||||||
|
float h = clamp(dot(pa, ba_norm), 0.0, length(ba));
|
||||||
|
float2 pb = p1 + ba_norm * h;
|
||||||
|
|
||||||
// 计算距离
|
float dist = length(p - pb); // 点到线段的距离
|
||||||
float2 d = abs(pos) - half_size;
|
float half_thickness = thickness / 2;
|
||||||
|
// 抗锯齿
|
||||||
|
float alpha = smoothstep(half_thickness - 1, half_thickness, dist);
|
||||||
|
// 圆角
|
||||||
|
float2 corner = float2(radius, radius);
|
||||||
|
float2 d = abs(p - pb) - corner;
|
||||||
|
float2 max_d = max(d, 0);
|
||||||
|
|
||||||
// 取最大值与0比较,确保不小于0
|
// float corner_dist = length(max_d);
|
||||||
float inside = length(max(d, 0.0)) - radius;
|
// float corner_alpha = smoothstep(0, 1, corner_dist);
|
||||||
|
|
||||||
// inside <= 0.0 说明在圆角矩形内
|
float4 color = input.color;
|
||||||
return input.color * step(inside, 0.0);
|
color.a *= (1 - alpha);
|
||||||
|
return color;
|
||||||
}
|
}
|
||||||
|
56
src/renderer/shader/aorii_sdf_text.slang
Normal file
56
src/renderer/shader/aorii_sdf_text.slang
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
struct VSInput {
|
||||||
|
float2 position : POSITION;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
float4 color : COLOR0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PSInput {
|
||||||
|
float4 position : SV_Position;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
float4 color : COLOR0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Constants {
|
||||||
|
matrix transform;
|
||||||
|
};
|
||||||
|
ParameterBlock<Constants> param_buffer : register(b0);
|
||||||
|
|
||||||
|
PSInput vertex_main(VSInput input) {
|
||||||
|
PSInput output;
|
||||||
|
output.position = mul(float4(input.position, 0.0f, 1.0f), param_buffer.transform);
|
||||||
|
output.uv = input.uv;
|
||||||
|
output.color = input.color;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D sdf_texture : register(t0);
|
||||||
|
SamplerState sdf_sampler : register(s0);
|
||||||
|
|
||||||
|
struct FontParams {
|
||||||
|
float smoothing; // 平滑度
|
||||||
|
float thickness; // 字体粗细
|
||||||
|
float outline_width; // 描边宽度
|
||||||
|
float4 outline_color; // 描边颜色
|
||||||
|
}
|
||||||
|
ParameterBlock<FontParams> font_param : register(b1);
|
||||||
|
|
||||||
|
float4 pixel_main(PSInput input) : SV_Target {
|
||||||
|
// 采样SDF纹理
|
||||||
|
float distance = sdf_texture.Sample(sdf_sampler, input.uv).r;
|
||||||
|
|
||||||
|
// 计算主要形状
|
||||||
|
float alpha = smoothstep(font_param.thickness - font_param.smoothing,
|
||||||
|
font_param.thickness + font_param.smoothing,
|
||||||
|
distance);
|
||||||
|
|
||||||
|
// 计算轮廓
|
||||||
|
float outline_alpha = smoothstep(font_param.thickness - font_param.outline_width - font_param.smoothing,
|
||||||
|
font_param.thickness - font_param.outline_width + font_param.smoothing,
|
||||||
|
distance);
|
||||||
|
|
||||||
|
// 混合主要颜色和轮廓颜色
|
||||||
|
float4 main_color = input.color * alpha;
|
||||||
|
float4 outline = font_param.outline_color * (outline_alpha - alpha);
|
||||||
|
|
||||||
|
return main_color + outline;
|
||||||
|
}
|
50
src/renderer/shader/aorii_segment.slang
Normal file
50
src/renderer/shader/aorii_segment.slang
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
struct VSInput {
|
||||||
|
float2 position : POSITION; // 窗口坐标
|
||||||
|
float2 uv : TEXCOORD0; // 纹理坐标
|
||||||
|
float4 color : COLOR; // 颜色
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PSInput {
|
||||||
|
float4 position : SV_POSITION; // 裁剪空间坐标
|
||||||
|
float2 uv : TEXCOORD0; // 纹理坐标
|
||||||
|
float4 color : COLOR; // 颜色
|
||||||
|
};
|
||||||
|
|
||||||
|
cbuffer segment_buffer : register(b0) {
|
||||||
|
matrix transform;
|
||||||
|
float2 pos_a; // 线段的起点
|
||||||
|
float2 pos_b; // 线段的终点
|
||||||
|
float thickness; // 线段的宽度
|
||||||
|
};
|
||||||
|
|
||||||
|
PSInput vertex_main(VSInput input) {
|
||||||
|
PSInput output;
|
||||||
|
output.position = mul(float4(input.position, 0.0, 1.0), transform);
|
||||||
|
output.color = input.color;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算点到线段的最短距mulnamespace离
|
||||||
|
float sdf_line(float2 p, float2 a, float2 b) {
|
||||||
|
float2 pa = p - a;
|
||||||
|
float2 ba = b - a;
|
||||||
|
|
||||||
|
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
||||||
|
return length(pa - ba * h);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 片段着色器
|
||||||
|
float4 pixel_main(PSInput input) : SV_TARGET {
|
||||||
|
// 将屏幕空间坐标转化为归一化设备坐标 (NDC)
|
||||||
|
float2 p = input.position.xy; // 归一化设备坐标 (NDC)
|
||||||
|
|
||||||
|
// 计算当前片段到线段的距离
|
||||||
|
float distance = sdf_line(p, pos_a, pos_b);
|
||||||
|
|
||||||
|
// 根据线段的粗细来决定颜色输出,使用抗锯齿处理
|
||||||
|
float alpha = smoothstep(thickness, thickness + 1, distance);
|
||||||
|
|
||||||
|
// 最终输出颜色,带上 alpha 通道
|
||||||
|
return float4(input.color.rgb, (1.0 - alpha) * input.color.a);
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user