封装着色器编译代码命令
编写部分注释
This commit is contained in:
parent
498a75c95f
commit
f73e7e4a50
@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 3.10)
|
||||
project(aorii)
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
set(SHADER_OUTPUT_DIR ${CMAKE_BINARY_DIR}/shader)
|
||||
|
||||
include(cmake/retrieve_files.cmake)
|
||||
include(cmake/detect_os.cmake)
|
||||
include(cmake/configure_glfw_native.cmake)
|
||||
@ -29,8 +27,3 @@ if (BUILD_EXAMPLE)
|
||||
add_subdirectory(example)
|
||||
endif ()
|
||||
|
||||
set(SHADER_STAGES
|
||||
"vertex"
|
||||
"pixel"
|
||||
)
|
||||
compile_slang_shaders(${CMAKE_CURRENT_SOURCE_DIR}/resource/shader/default_shader.slang SHADER_STAGES)
|
||||
|
@ -1,87 +1,84 @@
|
||||
function(compile_slang_shaders input_shaders shader_stages)
|
||||
# Ensure the output directory exists
|
||||
|
||||
function(compile_slang_shaders input_file stage entry_point)
|
||||
# 保证输出目录存在
|
||||
if (NOT DEFINED SHADER_OUTPUT_DIR)
|
||||
message(FATAL_ERROR "SHADER_OUTPUT_DIR not defined")
|
||||
endif ()
|
||||
set(output_dir ${SHADER_OUTPUT_DIR})
|
||||
file(MAKE_DIRECTORY ${output_dir})
|
||||
|
||||
foreach(input_file IN LISTS input_shaders)
|
||||
# Get the base name for the output file
|
||||
get_filename_component(filename ${input_file} NAME_WE)
|
||||
# 获取输出文件的基本名称
|
||||
get_filename_component(filename ${input_file} NAME_WE)
|
||||
|
||||
# Initialize a list to hold all the output files for this shader
|
||||
set(output_files)
|
||||
# 定义根据阶段确定的配置
|
||||
if(stage STREQUAL "vertex")
|
||||
set(profile "vs_5_0")
|
||||
elseif(stage STREQUAL "pixel")
|
||||
set(profile "ps_5_0")
|
||||
elseif (stage STREQUAL "comp")
|
||||
set(profile "cs_5_0")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported shader stage: ${stage}")
|
||||
endif()
|
||||
|
||||
# Use a set to track processed stages to avoid duplication
|
||||
set(processed_stages)
|
||||
# 初始化一个列表来存储输出文件
|
||||
set(output_files)
|
||||
|
||||
foreach(stage IN LISTS ${shader_stages})
|
||||
# Check if the stage has already been processed
|
||||
if(NOT stage IN_LIST processed_stages)
|
||||
list(APPEND processed_stages ${stage})
|
||||
|
||||
# Define the entry point based on the stage
|
||||
if(stage STREQUAL "vertex")
|
||||
set(entry_point "vertex_main")
|
||||
set(profile "vs_5_0")
|
||||
elseif(stage STREQUAL "pixel")
|
||||
set(entry_point "pixel_main")
|
||||
set(profile "ps_5_0")
|
||||
elseif (stage STREQUAL "comp")
|
||||
set(entry_point "compute_main")
|
||||
set(profile "cs_5_0")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported shader stage: ${stage}")
|
||||
endif()
|
||||
|
||||
# Check and compile for each backend
|
||||
if(GL_BACKEND)
|
||||
list(APPEND output_files ${output_dir}/${filename}_${stage}.glsl)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_dir}/${filename}_${stage}.glsl
|
||||
COMMAND slangc -target glsl -entry ${entry_point} -stage ${stage} -o ${output_dir}/${filename}_${stage}.glsl ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to GLSL (${stage})"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(DX_BACKEND)
|
||||
list(APPEND output_files ${output_dir}/${filename}_${stage}.dxbc)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_dir}/${filename}_${stage}.dxbc
|
||||
COMMAND slangc -target dxbc -profile ${profile} -entry ${entry_point} -stage ${stage} -o ${output_dir}/${filename}_${stage}.dxbc ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to DXBC (${stage})"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(VK_BACKEND)
|
||||
list(APPEND output_files ${output_dir}/${filename}_${stage}.spirv)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_dir}/${filename}_${stage}.spirv
|
||||
COMMAND slangc -target spirv -entry ${entry_point} -stage ${stage} -o ${output_dir}/${filename}_${stage}.spirv ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to SPIR-V (${stage})"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(METAL_BACKEND)
|
||||
list(APPEND output_files ${output_dir}/${filename}_${stage}.metal)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_dir}/${filename}_${stage}.metal
|
||||
COMMAND slangc -target msl -entry ${entry_point} -stage ${stage} -o ${output_dir}/${filename}_${stage}.metal ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to Metal Shading Language (${stage})"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "The stage '${stage}' has already been processed for entry point '${entry_point}'. Skipping duplicate.")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Add the custom command outputs to the compile_shader target
|
||||
add_custom_target(
|
||||
compile_shader
|
||||
DEPENDS ${output_files}
|
||||
# 为每个后台创建自定义命令
|
||||
if(GL_BACKEND)
|
||||
set(output_file ${output_dir}/${filename}_${entry_point}.glsl)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_file}
|
||||
COMMAND slangc -target glsl -entry ${entry_point} -stage ${stage} -o ${output_file} ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to GLSL (${stage}, ${entry_point})"
|
||||
)
|
||||
endforeach()
|
||||
list(APPEND output_files ${output_file})
|
||||
endif()
|
||||
|
||||
if(DX_BACKEND)
|
||||
set(output_file ${output_dir}/${filename}_${entry_point}.dxbc)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_file}
|
||||
COMMAND slangc -target dxbc -profile ${profile} -entry ${entry_point} -stage ${stage} -o ${output_file} ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to DXBC (${stage}, ${entry_point}) with profile ${profile}"
|
||||
)
|
||||
list(APPEND output_files ${output_file})
|
||||
endif()
|
||||
|
||||
if(VK_BACKEND)
|
||||
set(output_file ${output_dir}/${filename}_${entry_point}.spirv)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_file}
|
||||
COMMAND slangc -target spirv -entry ${entry_point} -stage ${stage} -o ${output_file} ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to SPIR-V (${stage}, ${entry_point})"
|
||||
)
|
||||
list(APPEND output_files ${output_file})
|
||||
endif()
|
||||
|
||||
if(METAL_BACKEND)
|
||||
set(output_file ${output_dir}/${filename}_${entry_point}.metal)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_file}
|
||||
COMMAND slangc -target msl -entry ${entry_point} -stage ${stage} -o ${output_file} ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to Metal Shading Language (${stage}, ${entry_point})"
|
||||
)
|
||||
list(APPEND output_files ${output_file})
|
||||
endif()
|
||||
|
||||
# 将输出文件添加到全局列表中
|
||||
set_property(GLOBAL APPEND PROPERTY ALL_SHADER_OUTPUTS ${output_files})
|
||||
endfunction()
|
||||
|
||||
function(add_compile_shaders_target target_name before_target)
|
||||
file(MAKE_DIRECTORY ${SHADER_OUTPUT_DIR})
|
||||
|
||||
get_property(ALL_SHADER_OUTPUTS GLOBAL PROPERTY ALL_SHADER_OUTPUTS)
|
||||
add_custom_target(${target_name} ALL DEPENDS ${ALL_SHADER_OUTPUTS})
|
||||
# 将编译着色器的目标添加到指定目标之前
|
||||
add_dependencies(${before_target} ${target_name})
|
||||
# 将ALL_SHADER_OUTPUTS清空
|
||||
set_property(GLOBAL PROPERTY ALL_SHADER_OUTPUTS "")
|
||||
endfunction()
|
||||
|
@ -5,3 +5,9 @@ set(SRC_FILES "")
|
||||
retrieve_files(src SRC_FILES)
|
||||
add_executable(${PROJECT_NAME} ${SRC_FILES})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE aorii_renderer)
|
||||
|
||||
# 复制${SHADER_OUTPUT_DIR}文件到${CMAKE_CURRENT_BINARY_DIR}/resource
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${SHADER_OUTPUT_DIR} $<TARGET_FILE_DIR:${PROJECT_NAME}>/resource/shaders
|
||||
COMMENT "Copying shader files to resource directory after build")
|
||||
|
@ -8,7 +8,7 @@ int main(int argc, char* argv[]) {
|
||||
aorii::create_renderer(renderer_api::dx11);
|
||||
aorii::create_window_manager();
|
||||
|
||||
auto window = aorii::create_window({128, 128}, "hello world");
|
||||
auto window = aorii::create_window({1280, 1280}, "hello world");
|
||||
auto glfw_window = window->get_glfw_window();
|
||||
while (!glfwWindowShouldClose(glfw_window)) {
|
||||
glfwPollEvents();
|
||||
|
@ -1,29 +0,0 @@
|
||||
struct MatrixBuffer
|
||||
{
|
||||
matrix transform;
|
||||
};
|
||||
ParameterBlock<MatrixBuffer> matrix_buffer : register(b0);
|
||||
SamplerState texture_sampler : register(s0);
|
||||
|
||||
struct VSInput {
|
||||
float2 position : POSITION;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
struct PSInput {
|
||||
float4 position : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
PSInput vertex_main(VSInput input)
|
||||
{
|
||||
PSInput output;
|
||||
output.position = mul(float4(input.position, 0.0, 1.0), matrix_buffer.transform);
|
||||
output.color = input.color;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 pixel_main(PSInput input) : SV_TARGET
|
||||
{
|
||||
return input.color;
|
||||
}
|
@ -54,3 +54,11 @@ foreach(BACKEND ${ALL_BACKENDS})
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC ${BACKEND}=0)
|
||||
endforeach()
|
||||
|
||||
if (NOT DEFINED SHADER_OUTPUT_DIR)
|
||||
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}")
|
||||
endif ()
|
||||
compile_slang_shaders(${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang vertex vertex_main)
|
||||
compile_slang_shaders(${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang pixel pixel_main)
|
||||
compile_slang_shaders(${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang pixel rounded_rect_pixel_main)
|
||||
add_compile_shaders_target("compile_aorii_shaders" ${PROJECT_NAME})
|
||||
|
@ -20,7 +20,7 @@ public:
|
||||
void build_index_buffer(int triangle_count);
|
||||
void build_constant_buffer();
|
||||
|
||||
void set_triangle(const std::span<const aorii_vertex_type>& in_vertexes, const std::span<const aorii_triangle_type>& in_triangles);
|
||||
void set_triangle(const std::span<const aorii_vertex_type>& in_vertexes, const std::span<const aorii_triangle_type>& in_triangles) override;
|
||||
|
||||
aorii_constant_buffer_type* lock_constant_buffer();
|
||||
void unlock_constant_buffer();
|
||||
|
@ -80,6 +80,7 @@ bool dx_window::create_surface(GLFWwindow* in_window) {
|
||||
|
||||
pipeline.load_pixel_shader();
|
||||
pipeline.load_vertex_shader();
|
||||
context.set_default_pipeline(&pipeline);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -103,15 +104,7 @@ void dx_window::begin_frame() {
|
||||
static float pos_y = 0;
|
||||
static bool draw_test = true;
|
||||
|
||||
auto delta_time = get_delta_time();
|
||||
|
||||
timer += delta_time;
|
||||
if (draw_test && timer.count() >= 0.01) {
|
||||
// float random_r = static_cast<float>(rand()) / RAND_MAX;
|
||||
// float random_g = static_cast<float>(rand()) / RAND_MAX;
|
||||
// float random_b = static_cast<float>(rand()) / RAND_MAX;
|
||||
// random_color = { random_r, random_g, random_b, 1.0f };
|
||||
|
||||
if (draw_test) {
|
||||
// 生成渐变色
|
||||
if (is_white) {
|
||||
if (random_color.r > 0) {
|
||||
@ -139,20 +132,16 @@ void dx_window::begin_frame() {
|
||||
}
|
||||
}
|
||||
|
||||
timer -= std::chrono::duration<double>(0.01);
|
||||
context.draw_rectangle({pos_x, pos_y}, {1, 1000}, random_color);
|
||||
context.draw_rectangle({ pos_x, pos_y }, { 1, 100 }, random_color);
|
||||
pos_x += 1;
|
||||
if (pos_x >= 1000) {
|
||||
pos_x = 0;
|
||||
draw_test = false;
|
||||
}
|
||||
}
|
||||
|
||||
pos_x += delta_time.count() * 100;
|
||||
if (pos_x >= 1000) {
|
||||
pos_x = 0;
|
||||
pos_y += 1;
|
||||
draw_test = false;
|
||||
}
|
||||
|
||||
pipeline.set_triangle(context.get_vertices(), context.get_triangles());
|
||||
}
|
||||
pipeline.draw();
|
||||
|
||||
context.flush();
|
||||
|
||||
swap_chain->Present(1, 0);
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <Eigen/Eigen>
|
||||
|
||||
#include "misc/color.h"
|
||||
|
||||
#define AORII_DEFAULT_PIXEL_SHADER_NAME "default_shader_pixel"
|
||||
#define AORII_DEFAULT_VERTEX_SHADER_NAME "default_shader_vertex"
|
||||
#define AORII_DEFAULT_PIXEL_SHADER_NAME "default_shader_pixel_main"
|
||||
#define AORII_DEFAULT_VERTEX_SHADER_NAME "default_shader_vertex_main"
|
||||
|
||||
struct aorii_vertex {
|
||||
Eigen::Vector2f position;
|
||||
@ -28,6 +29,8 @@ public:
|
||||
|
||||
virtual void use() = 0;
|
||||
virtual void draw() = 0;
|
||||
|
||||
virtual void set_triangle(const std::span<const aorii_vertex_type>& in_vertexes, const std::span<const aorii_triangle_type>& in_triangles) = 0;
|
||||
};
|
||||
|
||||
class custom_pipeline : public pipeline {
|
||||
|
@ -13,10 +13,6 @@ enum class renderer_api {
|
||||
metal,
|
||||
};
|
||||
|
||||
struct vertex_data {
|
||||
Eigen::Vector3f position;
|
||||
};
|
||||
|
||||
class renderer {
|
||||
friend class window_manager;
|
||||
public:
|
||||
@ -49,7 +45,7 @@ namespace aorii {
|
||||
|
||||
const std::chrono::duration<double>& get_delta_time();
|
||||
|
||||
inline std::filesystem::path s_shader_relative_path = "resource/shader";
|
||||
inline std::filesystem::path s_shader_relative_path = "resource/shaders";
|
||||
inline void set_shader_relative_path(const std::filesystem::path& path) { s_shader_relative_path = path; }
|
||||
inline std::filesystem::path get_shader_path(const std::string& shader_name) { return std::filesystem::current_path() / s_shader_relative_path / shader_name; }
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
#include "renderer_context.h"
|
||||
|
||||
void renderer_context::draw_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size,
|
||||
const linear_color& in_color) {
|
||||
|
||||
const aorii_vertex_type v1 {{in_pos.x(), in_pos.y()}, in_color }; // 左上角
|
||||
const aorii_vertex_type v2 {{in_pos.x() + in_size.x(), in_pos.y()}, in_color }; // 右上角
|
||||
const aorii_vertex_type v3 {{in_pos.x(), in_pos.y() + in_size.y()}, in_color }; // 左下角
|
||||
const aorii_vertex_type v4 {{in_pos.x() + in_size.x(), in_pos.y() + in_size.y()}, in_color }; // 右下角
|
||||
void renderer_context::draw_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color) {
|
||||
switch_pipeline(default_pipeline);
|
||||
const aorii_vertex_type v1{ { in_pos.x(), in_pos.y() }, in_color }; // 左上角
|
||||
const aorii_vertex_type v2{ { in_pos.x() + in_size.x(), in_pos.y() }, in_color }; // 右上角
|
||||
const aorii_vertex_type v3{ { in_pos.x(), in_pos.y() + in_size.y() }, in_color }; // 左下角
|
||||
const aorii_vertex_type v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, in_color }; // 右下角
|
||||
|
||||
const uint32_t index1 = vertices.size();
|
||||
vertices.push_back(v1);
|
||||
@ -17,22 +16,29 @@ void renderer_context::draw_rectangle(const Eigen::Vector2i& in_pos, const Eigen
|
||||
const uint32_t index4 = vertices.size();
|
||||
vertices.push_back(v4);
|
||||
|
||||
const aorii_triangle_type t1 = {index1, index2, index3};
|
||||
const aorii_triangle_type t2 = {index2, index3, index4};
|
||||
const aorii_triangle_type t1 = { index1, index2, index3 };
|
||||
const aorii_triangle_type t2 = { index2, index3, index4 };
|
||||
triangles.push_back(t1);
|
||||
triangles.push_back(t2);
|
||||
}
|
||||
|
||||
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_rounded_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color, float in_radius) {
|
||||
switch_pipeline(rounded_rectangular_pipeline);
|
||||
|
||||
// 立刻绘制并重置管线, 因为下一个绘制命令的参数可能不同, 所以无法合批
|
||||
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) {
|
||||
switch_pipeline(default_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 normal = { -direction.y(), direction.x() };
|
||||
const Eigen::Vector2f offset = normal * in_thickness;
|
||||
|
||||
const aorii_vertex_type v1 {{in_pos_p1.x() + offset.x(), in_pos_p1.y() + offset.y()}, in_color };
|
||||
const aorii_vertex_type v2 {{in_pos_p1.x() - offset.x(), in_pos_p1.y() - offset.y()}, in_color };
|
||||
const aorii_vertex_type v3 {{in_pos_p2.x() + offset.x(), in_pos_p2.y() + offset.y()}, in_color };
|
||||
const aorii_vertex_type v4 {{in_pos_p2.x() - offset.x(), in_pos_p2.y() - offset.y()}, in_color };
|
||||
const aorii_vertex_type v1{ { in_pos_p1.x() + offset.x(), in_pos_p1.y() + offset.y() }, in_color };
|
||||
const aorii_vertex_type v2{ { in_pos_p1.x() - offset.x(), in_pos_p1.y() - offset.y() }, in_color };
|
||||
const aorii_vertex_type v3{ { in_pos_p2.x() + offset.x(), in_pos_p2.y() + offset.y() }, in_color };
|
||||
const aorii_vertex_type v4{ { in_pos_p2.x() - offset.x(), in_pos_p2.y() - offset.y() }, in_color };
|
||||
|
||||
const uint32_t index1 = vertices.size();
|
||||
vertices.push_back(v1);
|
||||
@ -43,8 +49,8 @@ void renderer_context::draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen::
|
||||
const uint32_t index4 = vertices.size();
|
||||
vertices.push_back(v4);
|
||||
|
||||
const aorii_triangle_type t1 = {index1, index2, index3};
|
||||
const aorii_triangle_type t2 = {index2, index3, index4};
|
||||
const aorii_triangle_type t1 = { index1, index2, index3 };
|
||||
const aorii_triangle_type t2 = { index2, index3, index4 };
|
||||
triangles.push_back(t1);
|
||||
triangles.push_back(t2);
|
||||
}
|
||||
|
@ -5,9 +5,36 @@
|
||||
|
||||
class renderer_context {
|
||||
public:
|
||||
/**
|
||||
* 绘制一个实心矩形
|
||||
* @param in_pos 当前控件坐标系的位置
|
||||
* @param in_size 绘制的大小(受控件缩放影响)
|
||||
* @param in_color 绘制的颜色
|
||||
*/
|
||||
void draw_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color);
|
||||
|
||||
/**
|
||||
* 绘制一个实心圆角矩形
|
||||
* @param in_pos 当前控件坐标系的位置
|
||||
* @param in_size 绘制的大小(受控件缩放影响)
|
||||
* @param in_color 绘制的颜色
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 绘制一条线
|
||||
* @param in_pos_p1 点1
|
||||
* @param in_pos_p2 点2
|
||||
* @param in_color 线颜色
|
||||
* @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 set_default_pipeline(pipeline* in_pipeline) {
|
||||
default_pipeline = in_pipeline;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
vertices.clear();
|
||||
triangles.clear();
|
||||
@ -19,8 +46,26 @@ public:
|
||||
[[nodiscard]] const std::vector<aorii_triangle_type>& get_triangles() const {
|
||||
return triangles;
|
||||
}
|
||||
void flush() {
|
||||
if (default_pipeline) {
|
||||
default_pipeline->set_triangle(vertices, triangles);
|
||||
default_pipeline->draw();
|
||||
}
|
||||
clear();
|
||||
}
|
||||
protected:
|
||||
void switch_pipeline(pipeline* in_pipeline) {
|
||||
if (current_pipeline != in_pipeline) {
|
||||
flush();
|
||||
current_pipeline = in_pipeline;
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<aorii_vertex_type> vertices;
|
||||
std::vector<aorii_triangle_type> triangles;
|
||||
void add_triangle(const Eigen::Vector2i& in_pos_p1, const Eigen::Vector2i& in_pos_p2, const Eigen::Vector2i& in_pos_p3);
|
||||
|
||||
pipeline* default_pipeline = nullptr;
|
||||
pipeline* rounded_rectangular_pipeline = nullptr;
|
||||
|
||||
pipeline* current_pipeline = nullptr;
|
||||
};
|
||||
|
63
src/renderer/shader/default_shader.slang
Normal file
63
src/renderer/shader/default_shader.slang
Normal file
@ -0,0 +1,63 @@
|
||||
struct MatrixBuffer
|
||||
{
|
||||
matrix transform;
|
||||
};
|
||||
struct RoundedRectBuffer
|
||||
{
|
||||
float2 size; // 像素单位
|
||||
float radius; // 像素单位
|
||||
};
|
||||
ParameterBlock<MatrixBuffer> matrix_buffer : register(b0);
|
||||
ParameterBlock<RoundedRectBuffer> rounded_rect_buffer : register(b1);
|
||||
SamplerState texture_sampler : register(s0);
|
||||
|
||||
struct VSInput {
|
||||
float2 position : POSITION;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
struct PSInput {
|
||||
float4 position : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
PSInput vertex_main(VSInput input)
|
||||
{
|
||||
PSInput output;
|
||||
output.position = mul(float4(input.position, 0.0, 1.0), matrix_buffer.transform);
|
||||
output.color = input.color;
|
||||
output.uv = input.position + 0.5;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 pixel_main(PSInput input) : SV_TARGET
|
||||
{
|
||||
return input.color;
|
||||
}
|
||||
|
||||
// 计算点到矩形边的最小距离
|
||||
float rounded_box_SDF(float2 center_position, float2 size, float radius)
|
||||
{
|
||||
float2 q = abs(center_position) - size + radius;
|
||||
return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
|
||||
}
|
||||
|
||||
// 圆角矩形像素着色器
|
||||
float4 rounded_rect_pixel_main(PSInput input) : SV_TARGET
|
||||
{
|
||||
float2 size = rounded_rect_buffer.size;
|
||||
float radius = rounded_rect_buffer.radius;
|
||||
|
||||
// 将UV坐标转换为中心坐标系统
|
||||
float2 center_position = (input.uv - 0.5) * size;
|
||||
|
||||
// 计算到圆角矩形边缘的距离
|
||||
float distance = rounded_box_SDF(center_position, size * 0.5, radius);
|
||||
|
||||
// 使用平滑步进函数创建抗锯齿边缘
|
||||
float alpha = 1.0 - smoothstep(-1.0, 1.0, distance);
|
||||
|
||||
// 返回最终颜色
|
||||
return float4(input.color.xyz, input.color.a * alpha);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user