diff --git a/.gitignore b/.gitignore index 21f4848..dfa80ea 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /cmake-build-release /.idea /scripts/shader_paths.txt +/cache/shader_loader.h diff --git a/cmake/compile_shaders.cmake b/cmake/compile_shaders.cmake index 89816de..e2f3108 100644 --- a/cmake/compile_shaders.cmake +++ b/cmake/compile_shaders.cmake @@ -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 ) diff --git a/scripts/compile_shaders.py b/scripts/compile_shaders.py index 5bcfe68..fb14fef 100644 --- a/scripts/compile_shaders.py +++ b/scripts/compile_shaders.py @@ -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 ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "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 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(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);", + "}", + "" + "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);", + "}", + ] + +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);", + " 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);", + " 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) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2d3e5df..56cb208 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -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 () diff --git a/src/core/mirage.cpp b/src/core/mirage.cpp index 516a3b6..dff1a94 100644 --- a/src/core/mirage.cpp +++ b/src/core/mirage.cpp @@ -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 diff --git a/src/core/mirage.h b/src/core/mirage.h index 0c63422..52736bd 100644 --- a/src/core/mirage.h +++ b/src/core/mirage.h @@ -1,8 +1,8 @@ #pragma once #include "LLGL/LLGL.h" #include "misc/mirage_type.h" -#include "window/window.h" #include +#include #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 + void llgl_deleter(T* ptr) { + if (auto renderer = get_renderer()) { + renderer->Release(*ptr); + } + } } diff --git a/src/core/misc/enum_class_flags.h b/src/core/misc/enum_class_flags.h new file mode 100644 index 0000000..f1bdc6c --- /dev/null +++ b/src/core/misc/enum_class_flags.h @@ -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 +constexpr bool enum_has_all_flags(Enum Flags, Enum Contains) +{ + using UnderlyingType = __underlying_type(Enum); + return ((UnderlyingType)Flags & (UnderlyingType)Contains) == (UnderlyingType)Contains; +} + +template +constexpr bool enum_has_any_flags(Enum Flags, Enum Contains) +{ + using UnderlyingType = __underlying_type(Enum); + return ((UnderlyingType)Flags & (UnderlyingType)Contains) != 0; +} + +template +void enum_add_flags(Enum& Flags, Enum FlagsToAdd) +{ + using UnderlyingType = __underlying_type(Enum); + Flags = (Enum)((UnderlyingType)Flags | (UnderlyingType)FlagsToAdd); +} + +template +void enum_remove_flags(Enum& Flags, Enum FlagsToRemove) +{ + using UnderlyingType = __underlying_type(Enum); + Flags = (Enum)((UnderlyingType)Flags & ~(UnderlyingType)FlagsToRemove); +} + diff --git a/src/core/misc/enums.h b/src/core/misc/enums.h new file mode 100644 index 0000000..ed7b68f --- /dev/null +++ b/src/core/misc/enums.h @@ -0,0 +1,8 @@ +#pragma once + +namespace mirage { + enum class orientation { + horizontal, + vertical + }; +} \ No newline at end of file diff --git a/src/core/misc/mirage_type.h b/src/core/misc/mirage_type.h index 68fffea..edca52f 100644 --- a/src/core/misc/mirage_type.h +++ b/src/core/misc/mirage_type.h @@ -2,10 +2,14 @@ #include #include "LLGL/LLGL.h" #include +#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; + using shader_ptr = std::shared_ptr; + using pipeline_layout_ptr = std::shared_ptr; 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 shaders; }; } diff --git a/src/core/renderer/draw_element.cpp b/src/core/renderer/draw_element.cpp new file mode 100644 index 0000000..54e0d4e --- /dev/null +++ b/src/core/renderer/draw_element.cpp @@ -0,0 +1 @@ +#include "draw_element.h" diff --git a/src/core/renderer/draw_element.h b/src/core/renderer/draw_element.h new file mode 100644 index 0000000..54182b9 --- /dev/null +++ b/src/core/renderer/draw_element.h @@ -0,0 +1,34 @@ +#pragma once +#include "rendering_common.h" +#include +#include + +namespace mirage { + + template + struct draw_element { + virtual ~draw_element() = default; + + static uint64_t batch_id() { + static uint32_t id = 0; + return reinterpret_cast(&id); + } + + virtual void submit(LLGL::CommandBuffer& in_command_buffer) = 0; + }; + + struct rounded_rect : draw_element { + 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; + }; +} diff --git a/src/core/renderer/element_batcher.cpp b/src/core/renderer/element_batcher.cpp deleted file mode 100644 index 0116b1b..0000000 --- a/src/core/renderer/element_batcher.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "element_batcher.h" diff --git a/src/core/renderer/element_batcher.h b/src/core/renderer/element_batcher.h deleted file mode 100644 index 56e15c6..0000000 --- a/src/core/renderer/element_batcher.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -namespace mirage { - class element_batcher { - - private: - struct batch_key { - - }; - }; -} diff --git a/src/core/renderer/render_buffer.cpp b/src/core/renderer/render_buffer.cpp index e0183cc..6304230 100644 --- a/src/core/renderer/render_buffer.cpp +++ b/src/core/renderer/render_buffer.cpp @@ -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"); diff --git a/src/core/renderer/render_buffer.h b/src/core/renderer/render_buffer.h index 9ea0961..cfbc5a7 100644 --- a/src/core/renderer/render_buffer.h +++ b/src/core/renderer/render_buffer.h @@ -1,7 +1,7 @@ #pragma once #include "LLGL/LLGL.h" #include "mirage.h" -#include "render_command_pool.h" +#include "rendering_common.h" #include namespace mirage { @@ -67,14 +67,46 @@ namespace mirage { void push(const void* data, size_t in_data_size); template - void push(std::span data) { + void push(const std::span& data) { push(data.data(), data.size_bytes()); } + template + void push(const std::vector& data) { + push(std::span(data)); + } template void push(const T& data) { push(&data, sizeof(T)); } + void update(const void* data, size_t offset, size_t size); + template + void update(std::span data, const size_t offset = 0) { + update(data.data(), offset, data.size_bytes()); + } + template + void update(const std::vector& data, const size_t offset = 0) { + update(std::span(data), offset); + } + template + 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 + void set(std::span in_data) { + set(in_data.data(), in_data.size_bytes()); + } + template + void set(const std::vector& in_data) { + set(std::span(in_data)); + } + template + 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 + std::shared_ptr 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(); + buffer->init(desc); + return buffer; + } + + template + std::shared_ptr 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(); + vertex_buffer->init(vertex_buffer_descriptor); + return vertex_buffer; + } + + template + std::shared_ptr 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(); + index_buffer->init(index_buffer_descriptor); + return index_buffer; + } } // namespace mirage diff --git a/src/core/renderer/render_context.cpp b/src/core/renderer/render_context.cpp index 7cb067d..dbc468c 100644 --- a/src/core/renderer/render_context.cpp +++ b/src/core/renderer/render_context.cpp @@ -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 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 diff --git a/src/core/renderer/render_context.h b/src/core/renderer/render_context.h index 37fa4d5..c21d51a 100644 --- a/src/core/renderer/render_context.h +++ b/src/core/renderer/render_context.h @@ -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 vertex_buffer; + std::shared_ptr index_buffer; + std::shared_ptr 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 diff --git a/src/core/renderer/render_draw_element.cpp b/src/core/renderer/render_draw_element.cpp deleted file mode 100644 index 0ea57c2..0000000 --- a/src/core/renderer/render_draw_element.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "render_draw_element.h" diff --git a/src/core/renderer/render_draw_element.h b/src/core/renderer/render_draw_element.h deleted file mode 100644 index 05b3df4..0000000 --- a/src/core/renderer/render_draw_element.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include - -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, ); - }; -} diff --git a/src/core/renderer/render_element_drawer.cpp b/src/core/renderer/render_element_drawer.cpp deleted file mode 100644 index 166d6d8..0000000 --- a/src/core/renderer/render_element_drawer.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "render_element_drawer.h" diff --git a/src/core/renderer/render_element_drawer.h b/src/core/renderer/render_element_drawer.h deleted file mode 100644 index efa849b..0000000 --- a/src/core/renderer/render_element_drawer.h +++ /dev/null @@ -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: - - }; -} diff --git a/src/core/renderer/render_window_element_list.cpp b/src/core/renderer/render_window_element_list.cpp deleted file mode 100644 index b5cf917..0000000 --- a/src/core/renderer/render_window_element_list.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "render_window_element_list.h" diff --git a/src/core/renderer/render_window_element_list.h b/src/core/renderer/render_window_element_list.h deleted file mode 100644 index c1b9eae..0000000 --- a/src/core/renderer/render_window_element_list.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -class render_window_element_list { -public: - render_window_element_list(); -private: - -}; diff --git a/src/core/renderer/rendering_common.h b/src/core/renderer/rendering_common.h index c90cac1..97c3517 100644 --- a/src/core/renderer/rendering_common.h +++ b/src/core/renderer/rendering_common.h @@ -1,244 +1,81 @@ #pragma once -#include #include "LLGL/LLGL.h" +#include "misc/enum_class_flags.h" #include +#include 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_ps)。参见slate_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, - }; - - /** - * 元素渲染时可应用的绘制效果 - * 注意:新增效果应以位掩码形式添加 - * 如果在此添加新类型,必须同时实现对应的着色器类型(TSlateElementPS)。参见SlateShaders.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 + vertex_shader_param(Eigen::Matrix 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 - 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(in_render_transform, in_local_position, in_color, in_secondary_color); - - return vertex; - } - - template - 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(in_render_transform, in_local_position, in_color, in_secondary_color); - - return vertex; - } - - - template - 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(in_render_transform, in_local_position, in_color, in_secondary_color); - - return vertex; - } - - template - 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(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(temp_pixel_size.x()); - vertex.pixel_size[1] = static_cast(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(in_render_transform, in_local_position, in_tex_coord, in_tex_coord2, in_color, in_secondary_color) - : make(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(in_render_transform, in_local_position, in_tex_coord, in_color, in_secondary_color) - : make(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(in_render_transform, in_local_position, in_tex_coord, in_color, in_secondary_color) - : make(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(in_render_transform, in_local_position, in_local_size, in_scale, in_tex_coord, in_color, in_secondary_color) - : make(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 - 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(); } }; } \ No newline at end of file diff --git a/src/core/shaders/aorii_util.slang b/src/core/shaders/aorii_util.slang index 1cfec2a..a4fc118 100644 --- a/src/core/shaders/aorii_util.slang +++ b/src/core/shaders/aorii_util.slang @@ -1,5 +1,5 @@ struct VSInput { - float3 position : POSITION; + float2 position : POSITION; float2 uv : TEXCOORD0; float4 color : COLOR0; float4 param_a : TEXCOORD1;