绘制功能

This commit is contained in:
Nanako 2025-02-23 16:34:46 +08:00
parent bad0f9ca55
commit 09304715ed
25 changed files with 763 additions and 457 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
/cmake-build-release
/.idea
/scripts/shader_paths.txt
/cache/shader_loader.h

View File

@ -12,6 +12,11 @@ message(STATUS "Python解释器: ${PYTHON_EXECUTABLE}")
message(STATUS "SLANG编译器: ${SLANG_COMPILER}")
set(SHADER_PATH_FILE ${CMAKE_CURRENT_SOURCE_DIR}/scripts/shader_paths.txt)
set(SHADER_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cache)
set(SHADER_HEADER_FILE ${SHADER_HEADER_DIR}/shader_loader.h)
#
file(WRITE ${SHADER_HEADER_FILE} "")
#
file(REMOVE ${SHADER_PATH_FILE})
@ -45,7 +50,7 @@ message(STATUS "着色器编译输出路径: ${SHADER_OUTPUT_DIR}")
# , , scripts/compile_shaders.py
add_custom_target(compile_shaders
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/compile_shaders.py --shader-list ${SHADER_PATH_FILE} --output-dir ${SHADER_OUTPUT_DIR} ${SLANGC_ARGS}
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/compile_shaders.py --header ${SHADER_HEADER_FILE} --shader-list ${SHADER_PATH_FILE} --output-dir ${SHADER_OUTPUT_DIR} ${SLANGC_ARGS}
COMMENT ""
VERBATIM
)

View File

@ -1,4 +1,7 @@
from typing import List, Tuple, Iterator, Optional
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import List, Tuple, Iterator
from pathlib import Path
import argparse
import subprocess
@ -6,21 +9,26 @@ import sys
import re
# 设置控制台输出编码
if sys.platform.startswith('win'):
# Windows系统下设置
sys.stdout.reconfigure(encoding='utf-8')
sys.stderr.reconfigure(encoding='utf-8')
# if sys.platform.startswith('win'):
# # Windows系统下设置
# sys.stdout.reconfigure(encoding='utf-8')
# sys.stderr.reconfigure(encoding='utf-8')
def print_utf8(message: str):
"""
以UTF-8编码打印消息
"""以UTF-8编码打印消息"""
print(message)
Args:
message: 要打印的消息
"""
print(message.encode('utf-8').decode(sys.stdout.encoding))
# 着色器类型和扩展名定义
SHADER_TYPES = {
'vertex': 'LLGL::ShaderType::Vertex',
'pixel': 'LLGL::ShaderType::Fragment',
'fragment': 'LLGL::ShaderType::Fragment',
'compute': 'LLGL::ShaderType::Compute',
'geometry': 'LLGL::ShaderType::Geometry',
'tess_control': 'LLGL::ShaderType::TessControl',
'tess_evaluation': 'LLGL::ShaderType::TessEvaluation'
}
# 常量定义
SHADER_EXTENSIONS = {
'glsl': 'glsl',
'spirv': 'spirv',
@ -34,104 +42,87 @@ SHADER_EXTENSIONS = {
TARGET_PROFILES = {
'glsl': ['-profile', 'glsl_460'],
'spirv': ['-profile', 'glsl_460', '-capability', 'glsl_spirv_1_6'],
'dxbc': ['-profile', 'sm_5_1'],
'dxbc': ['-profile', 'sm_5_0'],
'dxil': ['-profile', 'sm_6_6'],
'metallib': ['-capability', 'metallib_3_1']
}
class ShaderEntry:
"""着色器入口点信息"""
def __init__(self, name: str, shader_type: str):
self.name = name
self.shader_type = shader_type
class CompiledShaderInfo:
"""编译后的着色器信息"""
def __init__(self, output_file: str, base: str, entry: ShaderEntry):
self.output_file = output_file
self.base = base
self.entry = entry
if entry.shader_type == 'pixel':
self.entry.shader_type = 'fragment'
# 存放所有编译成功的着色器信息
compiled_shaders: List[CompiledShaderInfo] = []
def find_shader_files(input_dir: Path, extensions: List[str]) -> Iterator[Path]:
"""
递归查找指定目录下的着色器文件
Args:
input_dir: 输入目录路径
extensions: 着色器文件扩展名列表
Yields:
符合扩展名的着色器文件路径
"""
"""递归查找指定目录下的着色器文件"""
for file_path in Path(input_dir).rglob('*'):
if file_path.suffix in extensions:
yield file_path
def find_slang_entries(input_file: Path) -> List[str]:
"""
从着色器文件中提取入口点函数名
Args:
input_file: 着色器文件路径
Returns:
入口点函数名列表
"""
# 匹配 [shader("xxx")] 形式的着色器入口点声明
pattern = re.compile(r'\[shader\(\s*"(?:\w+)"\s*\)\]\s*\n\s*\w+\s+(\w+)\s*\(')
def find_slang_entries(input_file: Path) -> List[ShaderEntry]:
"""从着色器文件中提取入口点函数名和类型"""
# 匹配 [shader("xxx")] 形式的着色器类型声明,以及后面的函数名
pattern = re.compile(
r'\[\s*shader\s*\(\s*"([^"]+)"\s*\)\s*\]\s*' # 匹配 [shader("xxx")]
r'(?:\[\s*[^\]]+\])*' # 可选:匹配其他属性如 [numthreads(8,8,1)]
r'\s*\w+\s+(\w+)\s*\(' # 匹配函数声明:返回类型 函数名(
)
try:
content = input_file.read_text(encoding='utf-8')
return list(set(pattern.findall(content)))
matches = pattern.findall(content)
print_utf8(f"**调试**: 在文件 {input_file} 中找到的匹配: {matches}")
entries = []
for shader_type, name in matches:
if shader_type in SHADER_TYPES:
entries.append(ShaderEntry(name, shader_type))
else:
print_utf8(f"**警告**: 未知的着色器类型 {shader_type}")
return entries
except Exception as e:
print_utf8(f"**错误**: 解析文件 {input_file} 失败: {e}")
return []
def get_shader_extension(build_type: str) -> str:
"""
根据构建类型获取对应的着色器文件扩展名
Args:
build_type: 构建类型
Returns:
对应的文件扩展名
"""
"""根据构建类型获取对应的着色器文件扩展名"""
return SHADER_EXTENSIONS.get(build_type, 'dat')
def create_compiler_command(
input_file: Path,
entry: str,
output_file: Path,
target_type: str,
args: argparse.Namespace
input_file: Path,
entry: ShaderEntry,
output_file: Path,
target_type: str,
args: argparse.Namespace
) -> List[str]:
"""
生成着色器编译命令
Args:
input_file: 输入文件路径
entry: 着色器入口点
output_file: 输出文件路径
target_type: 目标平台类型
args: 命令行参数
Returns:
编译命令列表
"""
"""生成着色器编译命令"""
cmd = [args.slangc,
str(input_file),
"-entry", entry,
"-entry", entry.name,
"-o", str(output_file),
"-target", target_type,
"-g3" if args.debug else "-O3"
]
# 添加优化或调试标志
"-g3" if args.debug else "-O3",
]
# 添加目标平台特定的编译选项
if target_type in TARGET_PROFILES:
cmd.extend(TARGET_PROFILES[target_type])
return cmd
def needs_recompile(input_file: Path, output_file: Path) -> bool:
"""
检查是否需要重新编译着色器
Args:
input_file: 输入文件路径
output_file: 输出文件路径
Returns:
是否需要重新编译
"""
"""检查是否需要重新编译着色器"""
if not output_file.exists():
return True
try:
@ -140,74 +131,287 @@ def needs_recompile(input_file: Path, output_file: Path) -> bool:
return True
def compile_shader(
input_file: Path,
target_types: List[Tuple[str, bool]],
output_dir: Path,
args: argparse.Namespace
input_file: Path,
target_types: List[Tuple[str, bool]],
output_dir: Path,
args: argparse.Namespace
) -> bool:
"""
编译单个着色器文件
Args:
input_file: 输入文件路径
target_types: 目标平台类型列表
output_dir: 输出目录
args: 命令行参数
Returns:
编译是否成功
"""
"""编译单个着色器文件"""
try:
# 获取着色器入口点
entries = find_slang_entries(input_file)
if not entries:
print_utf8(f"**跳过**: {input_file} - 未找到着色器入口点")
return True
# 创建输出目录
output_dir.mkdir(parents=True, exist_ok=True)
base = input_file.stem
success = True
# 针对每个目标平台编译
for entry in entries:
compiled_shaders.append(CompiledShaderInfo(f"{base}_{entry.name}", base, entry))
for target_type, enabled in target_types:
if not enabled:
continue
for entry in entries:
output_file = output_dir / f"{base}_{entry}.{get_shader_extension(target_type)}"
# 检查是否需要重新编译
output_file = output_dir / f"{base}_{entry.name}.{get_shader_extension(target_type)}"
if not needs_recompile(input_file, output_file):
print_utf8(f"**跳过**: {output_file} - 文件已是最新")
continue
# 执行编译
cmd = create_compiler_command(input_file, entry, output_file, target_type, args)
try:
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
print_utf8(f"**成功**: 编译 {input_file}:{entry} -> {output_file}")
except subprocess.CalledProcessError as e:
print_utf8(f"**错误**: 编译 {input_file}:{entry} 失败")
print_utf8(e.stderr)
success = False
else:
cmd = create_compiler_command(input_file, entry, output_file, target_type, args)
try:
subprocess.run(cmd, check=True, capture_output=True, text=True)
print_utf8(f"**成功**: 编译 {input_file}:{entry.name} -> {output_file}")
except subprocess.CalledProcessError as e:
print_utf8(f"**错误**: 编译 {input_file}:{entry.name} 失败")
print_utf8(e.stderr)
success = False
continue
return success
except Exception as e:
print_utf8(f"**错误**: 处理 {input_file} 时发生异常: {e}")
return False
def generate_pipeline_header_preamble() -> List[str]:
"""Generate the header file preamble"""
return [
"#pragma once",
"",
"#include \"mirage.h\"",
"#include \"misc/mirage_type.h\"",
"#include <LLGL/LLGL.h>",
"#include <LLGL/Utils/VertexFormat.h>",
"#include <memory>",
"#include <string>",
"#include <vector>",
"#include <fstream>",
"#include <stdexcept>",
"",
"namespace generated_pipelines {",
"",
"// 辅助函数:加载着色器",
"inline auto LoadShader(",
" LLGL::RenderSystem* renderer,",
" const std::string& filename,",
" const LLGL::ShaderType type,",
" const char* entryPoint,",
" const LLGL::ShaderDescriptor& shaderDesc = {}) {",
"",
" // 根据渲染器类型选择着色器文件后缀",
" auto rendererID = renderer->GetRendererID();",
" std::string ext;",
" // 选择对应的文件扩展名",
" if (rendererID == LLGL::RendererID::OpenGL) {",
" ext = \".glsl\";",
" } else if (rendererID == LLGL::RendererID::Vulkan) {",
" ext = \".spirv\";",
" } else if (rendererID == LLGL::RendererID::Direct3D11) {",
" ext = \".dxbc\";",
" } else if (rendererID == LLGL::RendererID::Direct3D12) {",
" ext = \".dxil\";",
" } else if (rendererID == LLGL::RendererID::Metal) {",
" ext = \".metallib\";",
" } else {",
" ext = \".dat\";",
" }",
"",
" // 构造最终的文件名",
" std::string finalFilename = filename;",
" size_t pos = finalFilename.find_last_of('.');",
" if (pos != std::string::npos) {",
" finalFilename = finalFilename.substr(0, pos) + ext;",
" } else {",
" finalFilename += ext;",
" }",
" finalFilename = (mirage::get_shader_path() / finalFilename).string();",
"",
" // 读取着色器文件",
" std::vector<char> shaderData;",
" try {",
" std::ifstream file(finalFilename, std::ios::binary | std::ios::ate);",
" if (!file.is_open()) {",
" throw std::runtime_error(\"Failed to open shader file: \" + finalFilename);",
" }",
" size_t fileSize = static_cast<size_t>(file.tellg());",
" shaderData.resize(fileSize);",
" file.seekg(0);",
" file.read(shaderData.data(), fileSize);",
" } catch (const std::exception& e) {",
" throw std::runtime_error(\"Failed to read shader file: \" + std::string(e.what()));",
" }",
"",
" // 创建着色器",
" LLGL::ShaderDescriptor desc = shaderDesc;",
" desc.source = shaderData.data();",
" desc.sourceSize = shaderData.size();",
" desc.entryPoint = entryPoint;",
" desc.type = type;",
" desc.sourceType = rendererID == LLGL::RendererID::OpenGL ? LLGL::ShaderSourceType::CodeString : LLGL::ShaderSourceType::BinaryBuffer;",
"",
" auto shader = renderer->CreateShader(desc);",
" if (auto report = shader->GetReport()) {",
" spdlog::error(\"Shader compilation report: {}\", report->GetText());",
" }",
" return mirage::shader_ptr(shader, mirage::llgl_deleter<LLGL::Shader>);",
"}",
""
"inline auto create_pipeline_layout(LLGL::RenderSystem* renderer, const LLGL::PipelineLayoutDescriptor& in_desc) {",
" auto pipelineLayout = renderer->CreatePipelineLayout(in_desc);",
" return mirage::pipeline_layout_ptr(pipelineLayout, mirage::llgl_deleter<LLGL::PipelineLayout>);",
"}",
]
def generate_compute_pipeline(header_lines: List[str], shader: CompiledShaderInfo):
"""Generate compute pipeline creation function"""
func_name = f"create_{shader.base}_{shader.entry.name}_pipeline"
header_lines.extend([
f"// 计算管线: {shader.base} - {shader.entry.name}",
f"inline auto {func_name}(LLGL::RenderSystem* renderer) {{",
" // 加载计算着色器",
f" auto computeShader = LoadShader(renderer, \"{shader.output_file.name}\", {SHADER_TYPES['compute']}, \"{shader.entry.name}\");",
"",
" // 创建管线布局",
" LLGL::PipelineLayoutDescriptor layoutDesc;",
" auto pipelineLayout = create_pipeline_layout(renderer, layoutDesc);",
"",
" // 创建计算管线",
" LLGL::ComputePipelineDescriptor pipelineDesc;",
" pipelineDesc.computeShader = computeShader.get();",
" pipelineDesc.pipelineLayout = pipelineLayout.get();",
"",
" auto pipeline = renderer->CreatePipelineState(pipelineDesc);",
" mirage::pipeline_info info;",
" info.pipeline_state = mirage::pipeline_state_ptr(pipeline, mirage::llgl_deleter<LLGL::PipelineState>);",
" info.pipeline_layout = pipelineLayout;",
" info.shaders = {computeShader};",
" return info;",
"}",
""
])
def generate_graphics_pipeline(header_lines: List[str], base: str, shaders: List[CompiledShaderInfo]):
"""Generate graphics pipeline creation function"""
func_name = f"create_{base}_pipeline"
header_lines.extend([
f"// 图形管线: {base}",
f"inline auto {func_name}(LLGL::RenderSystem* renderer, const LLGL::RenderPass* render_pass, const LLGL::PipelineLayoutDescriptor& in_pipeline_layout_desc, const LLGL::VertexFormat& vertex_format = mirage::create_vertex_format()) {{",
f" // 加载各个阶段的着色器",
f" LLGL::ShaderDescriptor vertexShaderDesc, fragShaderDesc;",
f" vertexShaderDesc.vertex.inputAttribs = vertex_format.attributes;",
])
SHADER_DESC_NAME = {
'vertex': 'vertexShaderDesc',
'pixel': 'fragShaderDesc',
'fragment': 'fragShaderDesc',
}
# Load all shader stages
for shader in shaders:
shader_type = shader.entry.shader_type
if shader_type in SHADER_TYPES:
header_lines.append(
f" auto {shader_type}Shader = LoadShader(renderer, "
f"\"{shader.output_file}\", {SHADER_TYPES[shader_type]}, "
f"\"{shader.entry.name}\", {SHADER_DESC_NAME[shader_type]});"
)
# Create pipeline layout and descriptor
header_lines.extend([
" // 创建管线布局",
" auto pipelineLayout = create_pipeline_layout(renderer, in_pipeline_layout_desc);",
"",
" // 创建图形管线",
" LLGL::GraphicsPipelineDescriptor pipelineDesc;",
])
# Set all shader stages
for shader in shaders:
shader_type = shader.entry.shader_type
if shader_type in SHADER_TYPES:
header_lines.append(f" pipelineDesc.{shader_type}Shader = {shader_type}Shader.get();")
# Set basic render states
header_lines.extend([
" pipelineDesc.pipelineLayout = pipelineLayout.get();",
"",
" // 设置基本渲染状态",
" pipelineDesc.renderPass = render_pass;",
" pipelineDesc.rasterizer.multiSampleEnabled = true;",
" pipelineDesc.blend.targets[0].blendEnabled = true;",
" pipelineDesc.depth.testEnabled = true;",
" pipelineDesc.depth.writeEnabled = true;",
"",
" auto pipeline = renderer->CreatePipelineState(pipelineDesc);",
])
# Finish function
header_lines.extend([
" mirage::pipeline_info info;",
" info.pipeline_state = mirage::pipeline_state_ptr(pipeline, mirage::llgl_deleter<LLGL::PipelineState>);",
" info.pipeline_layout = pipelineLayout;",
" info.shaders = {",
])
for shader in shaders:
shader_type = shader.entry.shader_type
if shader_type in SHADER_TYPES:
header_lines.append(f" {shader_type}Shader,")
header_lines.append(" };")
header_lines.extend([
" return info;",
"}",
""
])
def generate_pipeline_header(header_path: Path):
"""Generate the complete pipeline header file"""
header_lines = generate_pipeline_header_preamble()
# Group shaders by base name
shader_groups = {}
for shader in compiled_shaders:
if shader.base not in shader_groups:
shader_groups[shader.base] = []
shader_groups[shader.base].append(shader)
# Generate pipeline functions
for base, shaders in shader_groups.items():
has_compute = any(s.entry.shader_type == "compute" for s in shaders)
if has_compute:
for shader in shaders:
if shader.entry.shader_type == "compute":
generate_compute_pipeline(header_lines, shader)
else:
generate_graphics_pipeline(header_lines, base, shaders)
# Close namespace
header_lines.extend([
"} // namespace generated_pipelines",
""
])
try:
header_path.write_text("\n".join(header_lines), encoding="utf-8")
print_utf8(f"**成功**: 生成管线 C++ 头文件 {header_path}")
except Exception as e:
print_utf8(f"**错误**: 写入头文件 {header_path} 失败: {e}")
def main():
"""
主函数解析命令行参数并执行编译流程
"""
# 设置UTF-8编码
"""主函数:解析命令行参数并执行编译流程"""
if sys.platform.startswith('win'):
# Windows下设置控制台代码页
subprocess.run(['chcp', '65001'], shell=True)
# 设置命令行参数
parser = argparse.ArgumentParser(description="使用 slangc 编译着色器")
parser = argparse.ArgumentParser(description="使用 slangc 编译着色器并生成 LLGL 渲染管线 C++ 头文件")
parser.add_argument("--shader-list", help="着色器列表文件路径")
parser.add_argument("--output-dir", help="输出目录")
parser.add_argument("--slangc", default="slangc", help="slangc 编译器路径")
@ -217,10 +421,10 @@ def main():
parser.add_argument("--d3d11", action="store_true", help="编译 D3D11 着色器")
parser.add_argument("--d3d12", action="store_true", help="编译 D3D12 着色器")
parser.add_argument("--metal", action="store_true", help="编译 Metal 着色器")
parser.add_argument("--header", help="生成的头文件路径")
args = parser.parse_args()
# 配置目标平台
target_types = [
['glsl', args.opengl],
['spirv', args.vulkan],
@ -229,21 +433,28 @@ def main():
['metallib', args.metal],
]
# 设置输出目录和着色器列表文件
output_dir = Path(args.output_dir or "shaders")
shader_list = Path(args.shader_list or "shader_paths.txt")
# 读取着色器路径列表
shader_paths = shader_list.read_text().splitlines()
try:
shader_paths = shader_list.read_text(encoding="utf-8").splitlines()
except Exception as e:
print_utf8(f"**错误**: 读取着色器列表文件 {shader_list} 失败: {e}")
sys.exit(1)
# 编译所有着色器
all_success = True
for shader_path in shader_paths:
shader_path = shader_path.strip()
for file in find_shader_files(shader_path, ['.slang']):
if not shader_path:
continue
for file in find_shader_files(Path(shader_path), ['.slang']):
if not compile_shader(file, target_types, output_dir, args):
all_success = False
# 输出到shader_list所在目录
header_file = Path(args.header or shader_list.parent / "generated_pipelines.h")
generate_pipeline_header(header_file)
if not all_success:
sys.exit(1)

View File

@ -29,10 +29,12 @@ find_package(Vulkan REQUIRED)
set(RENDERER_SOURCES "")
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR} RENDERER_SOURCES)
#
list(APPEND RENDERER_SOURCES ${SHADER_HEADER_FILE})
add_library(${PROJECT_NAME} STATIC ${RENDERER_SOURCES})
target_link_libraries(${PROJECT_NAME} PUBLIC Freetype::Freetype harfbuzz Eigen3::Eigen spdlog::spdlog msdfgen-full Boost::boost Vulkan::Vulkan LLGL)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${SHADER_HEADER_DIR})
target_compile_definitions(${PROJECT_NAME} PRIVATE NOMINMAX)
add_os_definitions(${PROJECT_NAME})
if (APPLE)
@ -44,3 +46,19 @@ endif ()
shader_compile_target(${CMAKE_CURRENT_SOURCE_DIR}/shaders)
# , mirage_core, compile_shaders
add_dependencies(${PROJECT_NAME} compile_shaders)
if (LLGL_BUILD_RENDERER_OPENGL OR LLGL_BUILD_RENDERER_OPENGLES3 OR LLGL_BUILD_RENDERER_WEBGL)
add_dependencies(${PROJECT_NAME} LLGL_OpenGL)
endif ()
if (LLGL_BUILD_RENDERER_VULKAN)
add_dependencies(${PROJECT_NAME} LLGL_Vulkan)
endif ()
if (LLGL_BUILD_RENDERER_DIRECT3D11)
add_dependencies(${PROJECT_NAME} LLGL_Direct3D11)
endif ()
if (LLGL_BUILD_RENDERER_DIRECT3D12)
add_dependencies(${PROJECT_NAME} LLGL_Direct3D12)
endif ()
if (LLGL_BUILD_RENDERER_METAL)
add_dependencies(${PROJECT_NAME} LLGL_Metal)
endif ()

View File

@ -7,6 +7,8 @@ mirage::duration_type delta_time = {};
mirage::time_type begin_time = {};
mirage::time_type last_time = {};
LLGL::RenderSystemPtr renderer = nullptr;
uint64_t frame_index = 0;
std::filesystem::path shader_path = "resource/shaders";
namespace mirage {
void on_llgl_log(LLGL::Log::ReportType type, const char* text, void* user_data) {
@ -128,6 +130,7 @@ namespace mirage {
}
while (!should_exit()) {
update();
frame_index++;
}
destroy();
} catch (const std::exception& e) {
@ -153,4 +156,15 @@ namespace mirage {
LLGL::CommandQueue* get_main_command_queue() {
return renderer->GetCommandQueue();
}
uint64_t get_frame_index() {
return frame_index;
}
std::filesystem::path get_shader_path() {
return shader_path;
}
void set_shader_path(const std::filesystem::path& in_shader_path) {
shader_path = in_shader_path;
}
} // namespace mirage

View File

@ -1,8 +1,8 @@
#pragma once
#include "LLGL/LLGL.h"
#include "misc/mirage_type.h"
#include "window/window.h"
#include <spdlog/spdlog.h>
#include <filesystem>
#define MIRAGE_VERSION_MAJOR 0
#define MIRAGE_VERSION_MINOR 1
@ -21,4 +21,15 @@ namespace mirage {
LLGL::RenderSystem* get_renderer();
LLGL::CommandQueue* get_main_command_queue();
uint64_t get_frame_index();
std::filesystem::path get_shader_path();
void set_shader_path(const std::filesystem::path& in_shader_path);
template<typename T>
void llgl_deleter(T* ptr) {
if (auto renderer = get_renderer()) {
renderer->Release(*ptr);
}
}
}

View File

@ -0,0 +1,52 @@
#pragma once
// Defines all bitwise operators for enum classes so it can be (mostly) used as a regular flags enum
#define ENUM_CLASS_FLAGS(Enum) \
inline Enum& operator|=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \
inline Enum& operator&=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \
inline Enum& operator^=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \
inline constexpr Enum operator| (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \
inline constexpr Enum operator& (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \
inline constexpr Enum operator^ (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \
inline constexpr bool operator! (Enum E) { return !(__underlying_type(Enum))E; } \
inline constexpr Enum operator~ (Enum E) { return (Enum)~(__underlying_type(Enum))E; }
// Friends all bitwise operators for enum classes so the definition can be kept private / protected.
#define FRIEND_ENUM_CLASS_FLAGS(Enum) \
friend Enum& operator|=(Enum& Lhs, Enum Rhs); \
friend Enum& operator&=(Enum& Lhs, Enum Rhs); \
friend Enum& operator^=(Enum& Lhs, Enum Rhs); \
friend constexpr Enum operator| (Enum Lhs, Enum Rhs); \
friend constexpr Enum operator& (Enum Lhs, Enum Rhs); \
friend constexpr Enum operator^ (Enum Lhs, Enum Rhs); \
friend constexpr bool operator! (Enum E); \
friend constexpr Enum operator~ (Enum E);
template<typename Enum>
constexpr bool enum_has_all_flags(Enum Flags, Enum Contains)
{
using UnderlyingType = __underlying_type(Enum);
return ((UnderlyingType)Flags & (UnderlyingType)Contains) == (UnderlyingType)Contains;
}
template<typename Enum>
constexpr bool enum_has_any_flags(Enum Flags, Enum Contains)
{
using UnderlyingType = __underlying_type(Enum);
return ((UnderlyingType)Flags & (UnderlyingType)Contains) != 0;
}
template<typename Enum>
void enum_add_flags(Enum& Flags, Enum FlagsToAdd)
{
using UnderlyingType = __underlying_type(Enum);
Flags = (Enum)((UnderlyingType)Flags | (UnderlyingType)FlagsToAdd);
}
template<typename Enum>
void enum_remove_flags(Enum& Flags, Enum FlagsToRemove)
{
using UnderlyingType = __underlying_type(Enum);
Flags = (Enum)((UnderlyingType)Flags & ~(UnderlyingType)FlagsToRemove);
}

8
src/core/misc/enums.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
namespace mirage {
enum class orientation {
horizontal,
vertical
};
}

View File

@ -2,10 +2,14 @@
#include <chrono>
#include "LLGL/LLGL.h"
#include <Eigen/Eigen>
#include "LLGL/Utils/VertexFormat.h"
namespace mirage {
using time_type = decltype(std::chrono::high_resolution_clock::now());
using duration_type = decltype(std::chrono::high_resolution_clock::now() - std::chrono::high_resolution_clock::now());
using pipeline_state_ptr = std::shared_ptr<LLGL::PipelineState>;
using shader_ptr = std::shared_ptr<LLGL::Shader>;
using pipeline_layout_ptr = std::shared_ptr<LLGL::PipelineLayout>;
enum class renderer_api {
dx11,
@ -57,6 +61,18 @@ namespace mirage {
return desc;
}
};
inline LLGL::VertexFormat create_vertex_format() {
LLGL::VertexFormat vertex_format;
vertex_format.AppendAttribute({"POSITION", 0, LLGL::Format::RG32Float}); // float2 position
vertex_format.AppendAttribute({"TEXCOORD", 0, LLGL::Format::RG32Float}); // float2 uv
vertex_format.AppendAttribute({"COLOR", 0, LLGL::Format::RGBA32Float}); // float4 color
vertex_format.AppendAttribute({"TEXCOORD", 1, LLGL::Format::RGBA32Float}); // float4 param_a
vertex_format.AppendAttribute({"TEXCOORD", 2, LLGL::Format::RGBA32Float}); // float4 param_b
vertex_format.AppendAttribute({"TEXCOORD", 3, LLGL::Format::RGBA32Float}); // float4 param_c
return vertex_format;
}
struct swap_chain_descriptor {
int color_bits = 32;
int depth_bits = 0;
@ -78,12 +94,13 @@ namespace mirage {
}
};
struct triangle_index_t {
int32_t vertex_index[3];
};
struct triangle_t {
vertex_t vertex[3];
struct pipeline_info {
pipeline_state_ptr pipeline_state;
pipeline_layout_ptr pipeline_layout;
std::vector<shader_ptr> shaders;
};
}

View File

@ -0,0 +1 @@
#include "draw_element.h"

View File

@ -0,0 +1,34 @@
#pragma once
#include "rendering_common.h"
#include <Eigen/Eigen>
#include <cstdint>
namespace mirage {
template<typename ElementType>
struct draw_element {
virtual ~draw_element() = default;
static uint64_t batch_id() {
static uint32_t id = 0;
return reinterpret_cast<uint64_t>(&id);
}
virtual void submit(LLGL::CommandBuffer& in_command_buffer) = 0;
};
struct rounded_rect : draw_element<rounded_rect> {
struct param {
Eigen::Matrix4f projection_matrix;
rect rect;
float left_top_radius;
float right_top_radius;
float right_bottom_radius;
float left_bottom_radius;
};
virtual void submit(LLGL::CommandBuffer& in_command_buffer) override {
}
param data;
};
}

View File

@ -1 +0,0 @@
#include "element_batcher.h"

View File

@ -1,11 +0,0 @@
#pragma once
namespace mirage {
class element_batcher {
private:
struct batch_key {
};
};
}

View File

@ -1,5 +1,7 @@
#include "render_buffer.h"
#include "render_command_pool.h"
namespace mirage {
render_buffer::~render_buffer() {
if (buffer) {
@ -12,7 +14,6 @@ namespace mirage {
}
LLGL::BufferDescriptor desc = in_desc;
desc.size = std::max(desc.size, DEFAULT_INITIAL_SIZE);
buffer = get_renderer()->CreateBuffer(desc);
if (!buffer) {
@ -92,6 +93,30 @@ namespace mirage {
}
size += in_data_size;
}
void render_buffer::update(const void* data, size_t offset, size_t size) {
if (offset + size > capacity) {
throw std::out_of_range("Buffer update out of bounds");
}
// 更新缓冲区
get_renderer()->WriteBuffer(*buffer, offset, data, size);
}
void render_buffer::set(const void* in_data, size_t in_size) {
if (in_size > capacity) {
resize(in_size);
}
if (access_flags & LLGL::CPUAccessFlags::Write) {
if (auto mapped = get_renderer()->MapBuffer(*buffer, LLGL::CPUAccess::WriteDiscard)) {
std::memcpy(mapped, in_data, in_size);
get_renderer()->UnmapBuffer(*buffer);
}
} else {
get_renderer()->WriteBuffer(*buffer, 0, in_data, in_size);
}
size = in_size;
}
void render_buffer::update_async(const void* data, size_t offset, size_t size) {
if (offset + size > capacity) {
throw std::out_of_range("Buffer update out of bounds");

View File

@ -1,7 +1,7 @@
#pragma once
#include "LLGL/LLGL.h"
#include "mirage.h"
#include "render_command_pool.h"
#include "rendering_common.h"
#include <span>
namespace mirage {
@ -67,14 +67,46 @@ namespace mirage {
void push(const void* data, size_t in_data_size);
template <typename T>
void push(std::span<const T> data) {
void push(const std::span<T>& data) {
push(data.data(), data.size_bytes());
}
template<typename T>
void push(const std::vector<T>& data) {
push(std::span(data));
}
template <class T>
void push(const T& data) {
push(&data, sizeof(T));
}
void update(const void* data, size_t offset, size_t size);
template<typename T>
void update(std::span<const T> data, const size_t offset = 0) {
update(data.data(), offset, data.size_bytes());
}
template<typename T>
void update(const std::vector<T>& data, const size_t offset = 0) {
update(std::span(data), offset);
}
template<typename T>
void update(const T& data, const size_t offset = 0) {
update(&data, offset, sizeof(T));
}
void set(const void* in_data, size_t in_size);
template<typename T>
void set(std::span<const T> in_data) {
set(in_data.data(), in_data.size_bytes());
}
template<typename T>
void set(const std::vector<T>& in_data) {
set(std::span(in_data));
}
template<typename T>
void set(const T& in_data) {
set(&in_data, sizeof(T));
}
// 异步更新缓冲区
struct update_info {
const void* data;
@ -100,11 +132,54 @@ namespace mirage {
operator bool() const {
return buffer;
}
auto& get_raw() const {
return *buffer;
}
private:
LLGL::Buffer* buffer;
size_t size;
size_t capacity;
long access_flags;
};
template<typename T>
std::shared_ptr<render_buffer> create_constant_buffer(long in_cpu_access_flags = LLGL::CPUAccessFlags::ReadWrite) {
LLGL::BufferDescriptor desc;
desc.size = sizeof(T);
desc.cpuAccessFlags = in_cpu_access_flags;
desc.bindFlags = LLGL::BindFlags::ConstantBuffer;
desc.miscFlags = LLGL::MiscFlags::DynamicUsage;
auto buffer = std::make_shared<render_buffer>();
buffer->init(desc);
return buffer;
}
template<typename T = vertex>
std::shared_ptr<render_buffer> create_vertex_buffer(const size_t in_count, const LLGL::VertexFormat& in_vertex_format = create_vertex_format()) {
LLGL::BufferDescriptor vertex_buffer_descriptor{};
vertex_buffer_descriptor.size = sizeof(T) * in_count;
vertex_buffer_descriptor.bindFlags = LLGL::BindFlags::VertexBuffer;
vertex_buffer_descriptor.miscFlags = LLGL::MiscFlags::DynamicUsage;
vertex_buffer_descriptor.cpuAccessFlags = LLGL::CPUAccessFlags::Write;
vertex_buffer_descriptor.vertexAttribs = in_vertex_format.attributes;
auto vertex_buffer = std::make_shared<render_buffer>();
vertex_buffer->init(vertex_buffer_descriptor);
return vertex_buffer;
}
template<typename T = triangle_index_t>
std::shared_ptr<render_buffer> create_index_buffer(const size_t in_count) {
LLGL::BufferDescriptor index_buffer_descriptor{};
index_buffer_descriptor.size = sizeof(T) * in_count;
index_buffer_descriptor.bindFlags = LLGL::BindFlags::IndexBuffer;
index_buffer_descriptor.miscFlags = LLGL::MiscFlags::DynamicUsage;
index_buffer_descriptor.cpuAccessFlags = LLGL::CPUAccessFlags::Write;
index_buffer_descriptor.format = LLGL::Format::R32UInt;
auto index_buffer = std::make_shared<render_buffer>();
index_buffer->init(index_buffer_descriptor);
return index_buffer;
}
} // namespace mirage

View File

@ -2,6 +2,13 @@
#include "LLGL/Utils/VertexFormat.h"
#include "mirage.h"
#include "rendering_common.h"
#include "shader_loader.h"
#include "LLGL/Utils/Parse.h"
struct pipeline_param {
Eigen::Matrix4f mvp;
};
namespace mirage {
render_context::~render_context() {
@ -23,8 +30,47 @@ namespace mirage {
return false;
}
set_vsync(in_desc.vsync);
create_vertex_buffer();
create_index_buffer();
vertex_buffer = create_vertex_buffer(64);
index_buffer = create_index_buffer(64);
param_buffer = create_constant_buffer<pipeline_param>();
pipeline_param param;
param.mvp = get_projection_matrix();
param_buffer->set(param);
LLGL::PipelineLayoutDescriptor pipeline_layout_desc;
pipeline_layout_desc.bindings.emplace_back(
LLGL::ResourceType::Buffer,
LLGL::BindFlags::ConstantBuffer,
LLGL::StageFlags::VertexStage,
0
);
pipeline = generated_pipelines::create_aorii_rect_pipeline(get_renderer(), swap_chain->GetRenderPass(), pipeline_layout_desc);
vertex va{};
va.position = {0.0f, 0.0f};
va.uv = {0.0f, 0.0f};
va.color = {1.0f, 1.0f, 0.0f, 1.0f};
vertex vb{};
vb.position = {100.0f, 0.0f};
vb.uv = {1.0f, 0.0f};
vb.color = {1.0f, 0.0f, 1.0f, 1.0f};
vertex vc{};
vc.position = {100.0f, 100.0f};
vc.uv = {1.0f, 1.0f};
vc.color = {0.0f, 1.0f, 1.0f, 1.0f};
vertex vd{};
vd.position = {0.0f, 100.0f};
vd.uv = {0.0f, 1.0f};
vd.color = {0.0f, 1.0f, 0.0f, 1.0f};
std::vector quad_vertices = {va, vb, vc, vd};
vertex_buffer->push(quad_vertices);
triangle_index_t ta{0, 1, 2};
triangle_index_t tb{0, 2, 3};
std::vector quad_indices = {ta, tb};
index_buffer->push(quad_indices);
return true;
}
render_context::update_status render_context::update(const duration_type& in_delta_time) {
@ -36,17 +82,33 @@ namespace mirage {
}
command_buffer->Begin();
{
command_buffer->SetViewport(swap_chain->GetResolution());
command_buffer->SetVertexBuffer(vertex_buffer->get_raw());
command_buffer->SetIndexBuffer(index_buffer->get_raw());
command_buffer->BeginRenderPass(*swap_chain);
command_buffer->Clear(LLGL::ClearFlags::Color, {0.1f, 0.1f, 0.2f, 1.0f});
{
command_buffer->Clear(LLGL::ClearFlags::Color, {0.1f, 0.1f, 0.2f, 1.0f});
command_buffer->SetPipelineState(*pipeline.pipeline_state);
command_buffer->SetResource(0, param_buffer->get_raw());
command_buffer->DrawIndexed(index_buffer->get_size() / sizeof(uint32_t), 0);
}
command_buffer->EndRenderPass();
}
command_buffer->End();
get_renderer()->GetCommandQueue()->Submit(*command_buffer);
swap_chain->Present();
return update_status::success;
}
void render_context::resize_swap_chain(const LLGL::Extent2D& in_size, long in_flag) {
if (swap_chain) {
swap_chain->ResizeBuffers(in_size, in_flag);
pipeline_param param;
param.mvp = get_projection_matrix();
param_buffer->set(param);
}
}
@ -58,28 +120,27 @@ namespace mirage {
}
}
void render_context::create_vertex_buffer() {
// 创建顶点格式布局
LLGL::VertexFormat vertexFormat;
// 添加顶点属性
vertexFormat.AppendAttribute({"position", LLGL::Format::RGB32Float}); // float3 position
vertexFormat.AppendAttribute({"texCoord0", LLGL::Format::RG32Float}); // float2 uv
vertexFormat.AppendAttribute({"color", LLGL::Format::RGBA32Float}); // float4 color
vertexFormat.AppendAttribute({"texCoord1", LLGL::Format::RGBA32Float}); // float4 param_a
vertexFormat.AppendAttribute({"texCoord2", LLGL::Format::RGBA32Float}); // float4 param_b
vertexFormat.AppendAttribute({"texCoord3", LLGL::Format::RGBA32Float}); // float4 param_c
LLGL::BufferDescriptor vertex_buffer_descriptor{};
vertex_buffer_descriptor.size = sizeof(vertex_t) * 512;
vertex_buffer_descriptor.bindFlags = LLGL::BindFlags::VertexBuffer;
vertex_buffer_descriptor.vertexAttribs = vertexFormat.attributes;
vertex_buffer.init(vertex_buffer_descriptor);
}
void render_context::create_index_buffer() {
LLGL::BufferDescriptor index_buffer_descriptor{};
index_buffer_descriptor.size = sizeof(triangle_index_t) * 512;
index_buffer_descriptor.bindFlags = LLGL::BindFlags::IndexBuffer;
index_buffer.init(index_buffer_descriptor);
Eigen::Matrix4f render_context::get_projection_matrix() const {
const bool is_clip_range_unit_cube = get_renderer()->GetRenderingCaps().clippingRange == LLGL::ClippingRange::MinusOneToOne;
const auto& size = swap_chain->GetResolution();
// 创建一个单位矩阵
Eigen::Matrix4f matrix = Eigen::Matrix4f::Identity();
// 透视投影矩阵
if (is_clip_range_unit_cube) {
matrix(0, 0) = 2.0f / size.width;
matrix(1, 1) = 2.0f / size.height;
matrix(2, 2) = 1.0f;
matrix(3, 3) = 1.0f;
matrix(3, 0) = -1.0f;
matrix(3, 1) = -1.0f;
} else {
matrix(0, 0) = 2.0f / size.width;
matrix(1, 1) = -2.0f / size.height;
matrix(2, 2) = 1.0f;
matrix(3, 3) = 1.0f;
matrix(3, 0) = -1.0f;
matrix(3, 1) = 1.0f;
}
return matrix;
}
} // namespace mirage

View File

@ -23,24 +23,19 @@ namespace mirage {
return swap_chain;
}
[[nodiscard]] size_t get_vertex_count() const {
return vertex_buffer.get_size() / sizeof(vertex_t);
}
[[nodiscard]] size_t get_index_count() const {
return index_buffer.get_size() / sizeof(triangle_index_t);
}
[[nodiscard]] Eigen::Vector2f get_size() const {
const auto& extent_2d = swap_chain->GetResolution();
return {extent_2d.width, extent_2d.height};
}
private:
void create_vertex_buffer();
void create_index_buffer();
render_buffer vertex_buffer;
render_buffer index_buffer;
[[nodiscard]] Eigen::Matrix4f get_projection_matrix() const;
private:
std::shared_ptr<render_buffer> vertex_buffer;
std::shared_ptr<render_buffer> index_buffer;
std::shared_ptr<render_buffer> param_buffer;
LLGL::CommandBuffer* command_buffer = nullptr;
LLGL::SwapChain* swap_chain = nullptr;
bool vsync = true;
LLGL::SwapChain* swap_chain = nullptr;
bool vsync = true;
pipeline_info pipeline;
};
} // namespace mirage

View File

@ -1 +0,0 @@
#include "render_draw_element.h"

View File

@ -1,14 +0,0 @@
#pragma once
#include <cstdint>
namespace mirage {
class render_draw_element {
public:
enum rotation_space {
local, // 相对于元素自身的坐标系 (0, 0)是元素的左上角
world // 相对于绘制几何体的坐标系 (0, 0)是屏幕的左上角
};
static void make_debug_quad(, uint32_t in_layer, );
};
}

View File

@ -1 +0,0 @@
#include "render_element_drawer.h"

View File

@ -1,22 +0,0 @@
#pragma once
#include "Eigen/Eigen"
namespace mirage {
struct rect_round {
float left_top_px;
float right_top_px;
float left_bottom_px;
float right_bottom_px;
};
enum class draw_effect {
none,
snap_to_pixel,
};
class element_drawer {
public:
void draw_rounded_rect(, Eigen::Vector2f in_pos, Eigen::Vector2f in_size, rect_round in_radius, Eigen::Vector4f in_color, draw_effect in_effect);
private:
};
}

View File

@ -1 +0,0 @@
#include "render_window_element_list.h"

View File

@ -1,8 +0,0 @@
#pragma once
class render_window_element_list {
public:
render_window_element_list();
private:
};

View File

@ -1,244 +1,81 @@
#pragma once
#include <cstdint>
#include "LLGL/LLGL.h"
#include "misc/enum_class_flags.h"
#include <Eigen/Eigen>
#include <cstdint>
namespace mirage {
using transform_type = Eigen::Affine2d;
using color_type = LLGL::ColorRGBAub;
using linear_color_type = LLGL::ColorRGBAf;
using point_type = Eigen::Vector2f;
/**
*
*/
enum class draw_primitive {
none,
line_list,
triangle_list,
};
/**
*
* tslate_element_psslate_shaders.h
*/
enum class shader_type {
/** 默认着色器类型,简单的纹理查找 */
default_ = 0,
/** 边框着色器 */
border = 1,
/** 灰度字体着色器使用仅alpha纹理 */
grayscale_font = 2,
/** 颜色字体着色器,使用颜色纹理 */
color_font = 3,
/** 线段着色器,用于绘制抗锯齿线条 */
line_segment = 4,
/** 完全自定义材质,不假设使用方式 */
custom = 5,
/** 后处理着色器 */
post_process = 6,
/** 圆角矩形着色器 */
rounded_box = 7,
};
/**
*
*
* TSlateElementPSSlateShaders.h
*/
enum class draw_effect {
/** 无效果 */
none = 0,
/** 高级:无混合模式绘制元素 */
no_blending = 1 << 0,
/** 高级使用预乘alpha混合。若设置了no_blending则忽略 */
pre_multiplied_alpha = 1 << 1,
/** 高级:不进行伽马校正 */
no_gamma = 1 << 2,
/** 高级将alpha值取反1 - Alpha */
invert_alpha = 1 << 3,
// ^^ 这些与ESlateBatchDrawFlag匹配 ^^
/** 禁用像素对齐 */
no_pixel_snapping = 1 << 4,
/** 以禁用效果绘制元素 */
disabled_effect = 1 << 5,
/** 高级忽略纹理alpha通道 */
ignore_texture_alpha = 1 << 6,
/** 高级:反转现有伽马校正 */
reverse_gamma = 1 << 7
};
enum class line_join_type {
// 使用锐边(斜接)连接线段
sharp = 0,
// 只需将线段拼接在一起
simple = 1,
};
/**
*
*/
enum class color_vision_deficiency {
normal_vision, // 正常视觉,
deuteranope, // 绿色盲/弱 (男性7%女性0.4%)
protanope, // 红色盲/弱 (男性2%女性0.01%)
tritanope, // 蓝色盲/弱 (男性0.0003%)
};
enum class mirage_vertex_rounding
{
disabled,
enabled
};
struct mirage_pixel_params {
struct vertex_shader_param {
union {
float x;
float r;
float x, a;
};
union {
float y;
float g;
float y, b;
};
union {
float z;
float b;
float z, c;
};
union {
float w;
float a;
float w, d;
};
mirage_pixel_params(float in_x, float in_y, float in_z, float in_w) : x(in_x), y(in_y), z(in_z), w(in_w) {}
mirage_pixel_params(const LLGL::ColorRGBAf& in) : r(in.r), g(in.g), b(in.b), a(in.a) {}
mirage_pixel_params(const LLGL::Offset2D& in) : x(in.x), y(in.y), z(0), w(0) {}
mirage_pixel_params(const LLGL::Extent2D& in) : x(in.width), y(in.height), z(0), w(0) {}
mirage_pixel_params(const LLGL::Offset3D& in) : x(in.x), y(in.y), z(in.z), w(0) {}
mirage_pixel_params(const LLGL::Extent3D& in) : x(in.width), y(in.height), z(in.depth), w(0) {}
mirage_pixel_params(const Eigen::Vector2f& in) : x(in.x()), y(in.y()), z(0), w(0) {}
mirage_pixel_params(const Eigen::Vector3f& in) : x(in.x()), y(in.y()), z(in.z()), w(0) {}
mirage_pixel_params(const Eigen::Vector4f& in) : x(in.x()), y(in.y()), z(in.z()), w(in.w()) {}
bool operator==(const mirage_pixel_params& in_other) const {
return x == in_other.x && y == in_other.y && z == in_other.z && w == in_other.w;
}
};
template<typename T>
vertex_shader_param(Eigen::Matrix<T, 4, 1> in_vec) : x(in_vec.x()), y(in_vec.y()), z(in_vec.z()), w(in_vec.w()) {}
vertex_shader_param() : x(0), y(0), z(0), w(0) {}
struct mirage_shader_params {
mirage_pixel_params pixel_params;
mirage_pixel_params pixel_params2;
mirage_pixel_params pixel_params3;
bool operator==(const mirage_shader_params& in_other) const {
return pixel_params == in_other.pixel_params && pixel_params2 == in_other.pixel_params2 && pixel_params3 == in_other.pixel_params3;
}
};
struct mirage_vertex {
// 纹理坐标 xy zw
float tex_coords[4];
// 纹理坐标用作自定义纹理的材质的传递
Eigen::Vector2f material_tex_coords;
// 顶点在窗口中的位置
Eigen::Vector2f position;
// 顶点颜色
color_type color;
// 次顶点颜色 一般用于轮廓
color_type secondary_color;
// 元素的局部大小
uint16_t pixel_size[2];
public:
template <mirage_vertex_rounding Rounding>
static mirage_vertex make(const transform_type& in_render_transform, const Eigen::Vector2f& in_local_position, const Eigen::Vector2f& in_tex_coord, const Eigen::Vector2f& in_tex_coord2, const color_type& in_color, const color_type& in_secondary_color = {}) {
mirage_vertex vertex{};
vertex.set_tex_coords(Eigen::Vector4f{in_tex_coord, in_tex_coord2});
vertex.init_common<Rounding>(in_render_transform, in_local_position, in_color, in_secondary_color);
return vertex;
}
template <mirage_vertex_rounding Rounding>
static mirage_vertex make(const transform_type& in_render_transform, const Eigen::Vector2f& in_local_position, const Eigen::Vector2f& in_tex_coord, const color_type& in_color, const color_type& in_secondary_color = {}) {
mirage_vertex vertex{};
vertex.set_tex_coords(in_tex_coord);
vertex.init_common<Rounding>(in_render_transform, in_local_position, in_color, in_secondary_color);
return vertex;
}
template <mirage_vertex_rounding Rounding>
static mirage_vertex make(const transform_type& in_render_transform, const Eigen::Vector2f& in_local_position, const Eigen::Vector4f& in_tex_coord, const color_type& in_color, const color_type& in_secondary_color = {}) {
mirage_vertex vertex{};
vertex.set_tex_coords(in_tex_coord);
vertex.init_common<Rounding>(in_render_transform, in_local_position, in_color, in_secondary_color);
return vertex;
}
template <mirage_vertex_rounding Rounding>
static mirage_vertex make(const transform_type& in_render_transform, const Eigen::Vector2f& in_local_position, const Eigen::Vector2f& in_local_size, float in_scale, const Eigen::Vector4f& in_tex_coord, const color_type& in_color, const color_type& in_secondary_color = {}) {
mirage_vertex vertex{};
vertex.set_tex_coords(in_tex_coord);
vertex.material_tex_coords = in_local_position.array() / in_local_size.array();
vertex.init_common<Rounding>(in_render_transform, in_local_position, in_color, in_secondary_color);
const Eigen::Vector2i temp_pixel_size = in_local_size * in_scale;
vertex.pixel_size[0] = static_cast<uint16_t>(temp_pixel_size.x());
vertex.pixel_size[1] = static_cast<uint16_t>(temp_pixel_size.y());
return vertex;
}
static mirage_vertex make(const transform_type& in_render_transform, const Eigen::Vector2f& in_local_position, const Eigen::Vector2f& in_tex_coord, const Eigen::Vector2f& in_tex_coord2, const color_type& in_color, const color_type& in_secondary_color = {}, mirage_vertex_rounding in_rounding = mirage_vertex_rounding::disabled) {
return in_rounding == mirage_vertex_rounding::enabled
? make<mirage_vertex_rounding::enabled>(in_render_transform, in_local_position, in_tex_coord, in_tex_coord2, in_color, in_secondary_color)
: make<mirage_vertex_rounding::disabled>(in_render_transform, in_local_position, in_tex_coord,in_tex_coord2, in_color, in_secondary_color);
}
static mirage_vertex make(const transform_type& in_render_transform, const Eigen::Vector2f& in_local_position, const Eigen::Vector2f& in_tex_coord, const color_type& in_color, const color_type& in_secondary_color = {}, mirage_vertex_rounding in_rounding = mirage_vertex_rounding::disabled) {
return in_rounding == mirage_vertex_rounding::enabled
? make<mirage_vertex_rounding::enabled>(in_render_transform, in_local_position, in_tex_coord, in_color, in_secondary_color)
: make<mirage_vertex_rounding::disabled>(in_render_transform, in_local_position, in_tex_coord, in_color, in_secondary_color);
}
static mirage_vertex make(const transform_type& in_render_transform, const Eigen::Vector2f& in_local_position, const Eigen::Vector4f& in_tex_coord, const color_type& in_color, const color_type& in_secondary_color = {}, mirage_vertex_rounding in_rounding = mirage_vertex_rounding::disabled) {
return in_rounding == mirage_vertex_rounding::enabled
? make<mirage_vertex_rounding::enabled>(in_render_transform, in_local_position, in_tex_coord, in_color, in_secondary_color)
: make<mirage_vertex_rounding::disabled>(in_render_transform, in_local_position, in_tex_coord, in_color, in_secondary_color);
}
static mirage_vertex make(const transform_type& in_render_transform, const Eigen::Vector2f& in_local_position, const Eigen::Vector2f& in_local_size, float in_scale, const Eigen::Vector4f& in_tex_coord, const color_type& in_color, const color_type& in_secondary_color = {},
mirage_vertex_rounding in_rounding = mirage_vertex_rounding::disabled) {
return in_rounding == mirage_vertex_rounding::enabled
? make<mirage_vertex_rounding::enabled>(in_render_transform, in_local_position, in_local_size, in_scale, in_tex_coord, in_color, in_secondary_color)
: make<mirage_vertex_rounding::disabled>(in_render_transform, in_local_position, in_local_size, in_scale, in_tex_coord, in_color, in_secondary_color);
}
void set_tex_coords(const Eigen::Vector4f& in_coords) {
tex_coords[0] = in_coords.x();
tex_coords[1] = in_coords.y();
tex_coords[2] = in_coords.z();
tex_coords[3] = in_coords.w();
}
void set_tex_coords(const Eigen::Vector2f& in_coords) {
tex_coords[0] = in_coords.x();
tex_coords[1] = in_coords.y();
tex_coords[2] = 1.f;
tex_coords[3] = 1.f;
}
void set_position(const Eigen::Vector2f& in_position) {
position = in_position;
}
private:
template <mirage_vertex_rounding Rounding>
void init_common(const transform_type& in_render_transform, const Eigen::Vector2f& in_local_position, const color_type& in_color, const color_type& in_secondary_color) {
position = in_render_transform * in_local_position;
if constexpr (Rounding == mirage_vertex_rounding::enabled) {
position = position.array().round().matrix();
float operator[](const std::size_t index) const {
switch (index) {
case 0:
return x;
case 1:
return y;
case 2:
return z;
case 3:
return w;
default:
return {};
}
color = in_color;
secondary_color = in_secondary_color;
}
};
struct vertex {
point_type position;
point_type uv;
linear_color_type color;
vertex_shader_param param[3];
};
struct triangle {
uint32_t index[3];
};
struct rect {
Eigen::Vector2f pos;
Eigen::Vector2f size;
[[nodiscard]] Eigen::Vector2f get_center() const {
return pos + size * 0.5f;
}
[[nodiscard]] Eigen::Vector2f get_top_left() const {
return pos;
}
[[nodiscard]] Eigen::Vector2f get_top_right() const {
return {pos.x() + size.x(), pos.y()};
}
[[nodiscard]] Eigen::Vector2f get_bottom_left() const {
return {pos.x(), pos.y() + size.y()};
}
[[nodiscard]] Eigen::Vector2f get_bottom_right() const {
return pos + size;
}
[[nodiscard]] bool contains_point(const Eigen::Vector2f& in_point) const {
return in_point.x() >= pos.x() && in_point.x() <= pos.x() + size.x() && in_point.y() >= pos.y() && in_point.y() <= pos.y() + size.y();
}
};
}

View File

@ -1,5 +1,5 @@
struct VSInput {
float3 position : POSITION;
float2 position : POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR0;
float4 param_a : TEXCOORD1;