着色器编译脚本
This commit is contained in:
parent
ba993e294c
commit
90500291f0
@ -3,14 +3,18 @@ find_program(PYTHON_EXECUTABLE python)
|
|||||||
find_program(GLSLANG_VALIDATOR glslangValidator)
|
find_program(GLSLANG_VALIDATOR glslangValidator)
|
||||||
find_program(SLANG_COMPILER slangc)
|
find_program(SLANG_COMPILER slangc)
|
||||||
|
|
||||||
|
set(SHADER_PATH_FILE ${CMAKE_CURRENT_SOURCE_DIR}/scripts/shader_paths.txt)
|
||||||
|
# 删除文件
|
||||||
|
file(REMOVE ${SHADER_PATH_FILE})
|
||||||
|
|
||||||
function(shader_compile_target INPUT_DIR)
|
function(shader_compile_target INPUT_DIR)
|
||||||
# 将路径拼接到全局着色器路径列表中
|
# 将路径写到scripts/shader_paths.txt中
|
||||||
list(APPEND SHADER_SOURCE_DIRS ${INPUT_DIR})
|
file(WRITE ${SHADER_PATH_FILE} ${INPUT_DIR})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# 添加自定义命令, 用于编译着色器, 调用scripts/compile_shaders.py
|
# 添加自定义命令, 用于编译着色器, 调用scripts/compile_shaders.py
|
||||||
add_custom_target(compile_aorii_shaders
|
add_custom_target(aorii_compile_shaders
|
||||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/compile_shaders.py --input-dir ${SHADER_SOURCE_DIRS} --output-dir ${SHADER_OUTPUT_DIR}
|
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/compile_shaders.py --output-dir ${SHADER_OUTPUT_DIR}
|
||||||
COMMENT "Compiling shaders"
|
COMMENT "Compiling shaders"
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
@ -10,15 +10,27 @@ def find_shader_files(input_dir, extensions):
|
|||||||
if any(file.endswith(ext) for ext in extensions):
|
if any(file.endswith(ext) for ext in extensions):
|
||||||
yield os.path.join(root, file)
|
yield os.path.join(root, file)
|
||||||
|
|
||||||
|
def has_glsl_main(input_file):
|
||||||
|
try:
|
||||||
|
with open(input_file, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
return "void main" in content
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error parsing {input_file}: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
def compile_glsl(input_file, output_dir, glslang_validator):
|
def compile_glsl(input_file, output_dir, glslang_validator):
|
||||||
try:
|
try:
|
||||||
|
if not has_glsl_main(input_file):
|
||||||
|
print(f"Skipping {input_file}: No main function found")
|
||||||
|
return True
|
||||||
|
|
||||||
base = os.path.splitext(os.path.basename(input_file))[0]
|
base = os.path.splitext(os.path.basename(input_file))[0]
|
||||||
ext = os.path.splitext(input_file)[1][1:]
|
ext = os.path.splitext(input_file)[1][1:]
|
||||||
relative_path = os.path.relpath(os.path.dirname(input_file), args.input_dir)
|
abs_path = os.path.abspath(output_dir)
|
||||||
output_subdir = os.path.join(output_dir, relative_path)
|
output_file = os.path.join(abs_path, f"{base}.{ext}.spv")
|
||||||
output_file = os.path.join(output_subdir, f"{base}.{ext}.spv")
|
|
||||||
|
|
||||||
os.makedirs(output_subdir, exist_ok=True)
|
os.makedirs(abs_path, exist_ok=True)
|
||||||
|
|
||||||
cmd = [glslang_validator, "-V", input_file, "-o", output_file]
|
cmd = [glslang_validator, "-V", input_file, "-o", output_file]
|
||||||
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
|
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
|
||||||
@ -34,7 +46,7 @@ def compile_glsl(input_file, output_dir, glslang_validator):
|
|||||||
|
|
||||||
def find_slang_entries(input_file):
|
def find_slang_entries(input_file):
|
||||||
try:
|
try:
|
||||||
with open(input_file, 'r') as f:
|
with open(input_file, 'r', encoding='utf-8') as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
pattern = r'\[shader\(\s*"(?:\w+)"\s*\)\]\s*\n\s*\w+\s+(\w+)\s*\('
|
pattern = r'\[shader\(\s*"(?:\w+)"\s*\)\]\s*\n\s*\w+\s+(\w+)\s*\('
|
||||||
return list(set(re.findall(pattern, content)))
|
return list(set(re.findall(pattern, content)))
|
||||||
@ -46,17 +58,18 @@ def compile_slang(input_file, output_dir, slangc):
|
|||||||
try:
|
try:
|
||||||
entries = find_slang_entries(input_file)
|
entries = find_slang_entries(input_file)
|
||||||
if not entries:
|
if not entries:
|
||||||
print(f"No entries found in {input_file}")
|
print(f"Skipping {input_file}: No shader entries found")
|
||||||
return False
|
return True
|
||||||
|
|
||||||
base = os.path.splitext(os.path.basename(input_file))[0]
|
base = os.path.splitext(os.path.basename(input_file))[0]
|
||||||
relative_path = os.path.relpath(os.path.dirname(input_file), args.input_dir)
|
|
||||||
output_subdir = os.path.join(output_dir, relative_path)
|
abs_path = os.path.abspath(output_dir)
|
||||||
os.makedirs(output_subdir, exist_ok=True)
|
|
||||||
|
os.makedirs(abs_path, exist_ok=True)
|
||||||
|
|
||||||
success = True
|
success = True
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
output_file = os.path.join(output_subdir, f"{base}_{entry}.spv")
|
output_file = os.path.join(abs_path, f"{base}_{entry}.spv")
|
||||||
cmd = [slangc, input_file, "-entry", entry, "-o", output_file, "-target", "spirv"]
|
cmd = [slangc, input_file, "-entry", entry, "-o", output_file, "-target", "spirv"]
|
||||||
try:
|
try:
|
||||||
subprocess.run(cmd, check=True, capture_output=True, text=True)
|
subprocess.run(cmd, check=True, capture_output=True, text=True)
|
||||||
@ -72,26 +85,32 @@ def compile_slang(input_file, output_dir, slangc):
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Compile shaders to SPIR-V")
|
parser = argparse.ArgumentParser(description="Compile shaders to SPIR-V")
|
||||||
parser.add_argument("--input-dir", required=True, help="Input directory containing shaders")
|
parser.add_argument("--output-dir", help="Output directory for SPIR-V files")
|
||||||
parser.add_argument("--output-dir", required=True, help="Output directory for SPIR-V files")
|
|
||||||
parser.add_argument("--glslang", default="glslangValidator", help="Path to glslangValidator")
|
parser.add_argument("--glslang", default="glslangValidator", help="Path to glslangValidator")
|
||||||
parser.add_argument("--slangc", default="slangc", help="Path to slangc")
|
parser.add_argument("--slangc", default="slangc", help="Path to slangc")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
output_dir = args.output_dir or "shaders"
|
||||||
|
|
||||||
|
# 读取当前同级目录下的shader_paths.txt
|
||||||
|
with open("shader_paths.txt", 'r') as f:
|
||||||
|
shader_paths = f.readlines()
|
||||||
|
|
||||||
glsl_ext = [".vert", ".frag", ".comp", ".geom", ".tesc", ".tese", ".glsl"]
|
glsl_ext = [".vert", ".frag", ".comp", ".geom", ".tesc", ".tese", ".glsl"]
|
||||||
slang_ext = [".slang"]
|
slang_ext = [".slang"]
|
||||||
|
|
||||||
all_success = True
|
all_success = True
|
||||||
|
|
||||||
# Compile GLSL
|
for shader_path in shader_paths:
|
||||||
for file in find_shader_files(args.input_dir, glsl_ext):
|
# Compile GLSL
|
||||||
if not compile_glsl(file, args.output_dir, args.glang):
|
for file in find_shader_files(shader_path, glsl_ext):
|
||||||
all_success = False
|
if not compile_glsl(file, output_dir, args.glslang):
|
||||||
|
all_success = False
|
||||||
|
|
||||||
# Compile Slang
|
# Compile Slang
|
||||||
for file in find_shader_files(args.input_dir, slang_ext):
|
for file in find_shader_files(shader_path, slang_ext):
|
||||||
if not compile_slang(file, args.output_dir, args.slangc):
|
if not compile_slang(file, output_dir, args.slangc):
|
||||||
all_success = False
|
all_success = False
|
||||||
|
|
||||||
if not all_success:
|
if not all_success:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -115,7 +115,7 @@ float3 get_subpixel_to_edge_distances(VSOutput input)
|
|||||||
return distances * distance_multiplier;
|
return distances * distance_multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Vertex Shader ----
|
[shader("vertex")]
|
||||||
VSOutput vertex_main(VSInput input)
|
VSOutput vertex_main(VSInput input)
|
||||||
{
|
{
|
||||||
VSOutput output;
|
VSOutput output;
|
||||||
@ -131,7 +131,7 @@ VSOutput vertex_main(VSInput input)
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Pixel Shader ----
|
[shader("pixel")]
|
||||||
PSOutput pixel_main(VSOutput input)
|
PSOutput pixel_main(VSOutput input)
|
||||||
{
|
{
|
||||||
PSOutput output;
|
PSOutput output;
|
@ -11,6 +11,7 @@ struct PSInput {
|
|||||||
float4 color : COLOR; // 颜色
|
float4 color : COLOR; // 颜色
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[shader("vertex")]
|
||||||
PSInput vertex_main(VSInput input)
|
PSInput vertex_main(VSInput input)
|
||||||
{
|
{
|
||||||
PSInput output;
|
PSInput output;
|
||||||
@ -19,6 +20,7 @@ PSInput vertex_main(VSInput input)
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[shader("pixel")]
|
||||||
float4 pixel_main(PSInput input) : SV_TARGET
|
float4 pixel_main(PSInput input) : SV_TARGET
|
||||||
{
|
{
|
||||||
return input.color;
|
return input.color;
|
@ -23,6 +23,7 @@ struct Constants {
|
|||||||
};
|
};
|
||||||
ParameterBlock<Constants> param_buffer : register(b0);
|
ParameterBlock<Constants> param_buffer : register(b0);
|
||||||
|
|
||||||
|
[shader("vertex")]
|
||||||
PSInput vertex_main(VSInput input) {
|
PSInput vertex_main(VSInput input) {
|
||||||
float2 altas_uv = input.param_a.xy;
|
float2 altas_uv = input.param_a.xy;
|
||||||
float2 char_size = input.param_b.xy;
|
float2 char_size = input.param_b.xy;
|
||||||
@ -41,6 +42,7 @@ PSInput vertex_main(VSInput input) {
|
|||||||
Texture2DArray atlas_texture : register(t0);
|
Texture2DArray atlas_texture : register(t0);
|
||||||
SamplerState sampler_state : register(s0);
|
SamplerState sampler_state : register(s0);
|
||||||
|
|
||||||
|
[shader("pixel")]
|
||||||
float4 pixel_main(PSInput input) : SV_Target {
|
float4 pixel_main(PSInput input) : SV_Target {
|
||||||
float2 uv = input.altas_uv + input.char_size * input.uv;
|
float2 uv = input.altas_uv + input.char_size * input.uv;
|
||||||
float distance = atlas_texture.Sample(sampler_state, float3(uv, input.altas_index)).r;
|
float distance = atlas_texture.Sample(sampler_state, float3(uv, input.altas_index)).r;
|
@ -14,6 +14,7 @@ cbuffer segment_buffer : register(b0) {
|
|||||||
float thickness; // 线段的宽度
|
float thickness; // 线段的宽度
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[shader("vertex")]
|
||||||
PSInput vertex_main(VSInput input) {
|
PSInput vertex_main(VSInput input) {
|
||||||
PSInput output;
|
PSInput output;
|
||||||
output.position = mul(float4(input.position, 0.0, 1.0), transform);
|
output.position = mul(float4(input.position, 0.0, 1.0), transform);
|
||||||
@ -30,7 +31,7 @@ float sdf_line(float2 p, float2 a, float2 b) {
|
|||||||
return length(pa - ba * h);
|
return length(pa - ba * h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 片段着色器
|
[shader("pixel")]
|
||||||
float4 pixel_main(PSInput input) : SV_TARGET {
|
float4 pixel_main(PSInput input) : SV_TARGET {
|
||||||
// 将屏幕空间坐标转化为归一化设备坐标 (NDC)
|
// 将屏幕空间坐标转化为归一化设备坐标 (NDC)
|
||||||
float2 p = input.position.xy; // 归一化设备坐标 (NDC)
|
float2 p = input.position.xy; // 归一化设备坐标 (NDC)
|
@ -15,6 +15,7 @@ struct PSInput {
|
|||||||
Texture2D<float4> texture;
|
Texture2D<float4> texture;
|
||||||
SamplerState sampler;
|
SamplerState sampler;
|
||||||
|
|
||||||
|
[shader("vertex")]
|
||||||
PSInput vertex_main(VSInput input)
|
PSInput vertex_main(VSInput input)
|
||||||
{
|
{
|
||||||
PSInput output;
|
PSInput output;
|
||||||
@ -24,6 +25,7 @@ PSInput vertex_main(VSInput input)
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[shader("pixel")]
|
||||||
float4 pixel_main(PSInput input) : SV_TARGET
|
float4 pixel_main(PSInput input) : SV_TARGET
|
||||||
{
|
{
|
||||||
return input.color * texture.Sample(sampler, input.uv);
|
return input.color * texture.Sample(sampler, input.uv);
|
Loading…
x
Reference in New Issue
Block a user