绘制功能
This commit is contained in:
parent
bad0f9ca55
commit
09304715ed
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
/cmake-build-release
|
||||
/.idea
|
||||
/scripts/shader_paths.txt
|
||||
/cache/shader_loader.h
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 ()
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
52
src/core/misc/enum_class_flags.h
Normal file
52
src/core/misc/enum_class_flags.h
Normal 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
8
src/core/misc/enums.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
namespace mirage {
|
||||
enum class orientation {
|
||||
horizontal,
|
||||
vertical
|
||||
};
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
1
src/core/renderer/draw_element.cpp
Normal file
1
src/core/renderer/draw_element.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "draw_element.h"
|
34
src/core/renderer/draw_element.h
Normal file
34
src/core/renderer/draw_element.h
Normal 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;
|
||||
};
|
||||
}
|
@ -1 +0,0 @@
|
||||
#include "element_batcher.h"
|
@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace mirage {
|
||||
class element_batcher {
|
||||
|
||||
private:
|
||||
struct batch_key {
|
||||
|
||||
};
|
||||
};
|
||||
}
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1 +0,0 @@
|
||||
#include "render_draw_element.h"
|
@ -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, );
|
||||
};
|
||||
}
|
@ -1 +0,0 @@
|
||||
#include "render_element_drawer.h"
|
@ -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:
|
||||
|
||||
};
|
||||
}
|
@ -1 +0,0 @@
|
||||
#include "render_window_element_list.h"
|
@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class render_window_element_list {
|
||||
public:
|
||||
render_window_element_list();
|
||||
private:
|
||||
|
||||
};
|
@ -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_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<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();
|
||||
}
|
||||
};
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
struct VSInput {
|
||||
float3 position : POSITION;
|
||||
float2 position : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 color : COLOR0;
|
||||
float4 param_a : TEXCOORD1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user