# Tuxanci 2 - A first person shooter # Copyright (C) 2007-2011 Tuxánci Development Team # Copyright (C) 2025-2026 Connor Thomson # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(SHADER_SLANG_PROFILE "spirv_1_5") set(SHADER_SLANG_TARGET "spirv") find_program(SLANGC_EXECUTABLE slangc) if(NOT SLANGC_EXECUTABLE) message(FATAL_ERROR "slangc is not found. Download it from https://github.com/shader-slang/slang and make sure it is in your PATH.") endif() find_program(XXD_EXECUTABLE NAMES xxd) if(NOT XXD_EXECUTABLE) message(FATAL_ERROR "xxd is not found. Make sure it is in your PATH.") endif() set(SHADER_EMBED_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/EmbedFile.cmake") function(target_compile_shaders TARGET_NAME) cmake_parse_arguments(PARSE_ARGV 1 ARG "" "PROFILE;ENTRY" "SHADERS") if(NOT ARG_PROFILE) set(ARG_PROFILE "${SHADER_SLANG_PROFILE}") endif() if(NOT ARG_ENTRY) set(ARG_ENTRY "main") endif() set(SPIRV_OUTPUTS "") foreach(SHADER ${ARG_SHADERS}) get_filename_component(SHADER_ABS "${SHADER}" ABSOLUTE) get_filename_component(SHADER_NAME "${SHADER}" NAME) set(_stage "") if(SHADER_NAME MATCHES "\\.vert\\.slang$") set(_stage "vertex") elseif(SHADER_NAME MATCHES "\\.frag\\.slang$") set(_stage "fragment") elseif(SHADER_NAME MATCHES "\\.comp\\.slang$") set(_stage "compute") elseif(SHADER_NAME MATCHES "\\.geom\\.slang$") set(_stage "geometry") elseif(SHADER_NAME MATCHES "\\.tesc\\.slang$") set(_stage "hull") elseif(SHADER_NAME MATCHES "\\.tese\\.slang$") set(_stage "domain") elseif(SHADER_NAME MATCHES "\\.rgen\\.slang$") set(_stage "raygeneration") elseif(SHADER_NAME MATCHES "\\.rchit\\.slang$") set(_stage "closesthit") elseif(SHADER_NAME MATCHES "\\.rmiss\\.slang$") set(_stage "miss") else() message(FATAL_ERROR "'${SHADER_NAME}' must end with ..slang") endif() set(SPIRV_OUT "${CMAKE_CURRENT_BINARY_DIR}/shaders/${SHADER_NAME}.spv") set(SPIRV_EMBED_C_OUT "${CMAKE_CURRENT_BINARY_DIR}/shaders/${SHADER_NAME}.xxd.c") string(REGEX REPLACE "[^A-Za-z0-9]" "_" SHADER_SYMBASE "${SHADER_NAME}.spv") set(SHADER_SYMBASE "file_${SHADER_SYMBASE}") add_custom_command( OUTPUT ${SPIRV_OUT} COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/shaders" COMMAND "${SLANGC_EXECUTABLE}" "${SHADER_ABS}" -target ${SHADER_SLANG_TARGET} -profile ${ARG_PROFILE} -entry ${ARG_ENTRY} -stage ${_stage} -o ${SPIRV_OUT} MAIN_DEPENDENCY "${SHADER_ABS}" COMMENT "Building SPIR-V ${SHADER_NAME}.spv" VERBATIM ) add_custom_command( OUTPUT ${SPIRV_EMBED_C_OUT} COMMAND ${CMAKE_COMMAND} -D IN_FILE=${SPIRV_OUT} -D OUT_C=${SPIRV_EMBED_C_OUT} -D SYMBASE=${SHADER_SYMBASE} -D XXD_EXE=${XXD_EXECUTABLE} -P "${SHADER_EMBED_SCRIPT}" DEPENDS ${SPIRV_OUT} "${SHADER_EMBED_SCRIPT}" COMMENT "Building C object ${SHADER_NAME}.spv.o" VERBATIM ) list(APPEND SPIRV_OUTPUTS ${SPIRV_EMBED_C_OUT}) endforeach() target_sources(${TARGET_NAME} PRIVATE ${SPIRV_OUTPUTS}) endfunction() function(target_embed_files TARGET_NAME) cmake_parse_arguments(PARSE_ARGV 1 ARG "" "" "FILES") set(EMBEDDED_OUTPUTS "") foreach(ASSET ${ARG_FILES}) get_filename_component(ASSET_ABS "${ASSET}" ABSOLUTE) file(RELATIVE_PATH ASSET_RELATIVE "${CMAKE_SOURCE_DIR}" "${ASSET_ABS}") string(REGEX REPLACE "[^A-Za-z0-9]" "_" ASSET_SYMBASE "${ASSET_RELATIVE}") set(ASSET_SYMBASE "file_${ASSET_SYMBASE}") get_filename_component(ASSET_NAME "${ASSET_RELATIVE}" NAME) set(ASSET_EMBED_C_OUT "${CMAKE_CURRENT_BINARY_DIR}/data/${ASSET_NAME}.xxd.c") add_custom_command( OUTPUT ${ASSET_EMBED_C_OUT} COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/data" COMMAND ${CMAKE_COMMAND} -D IN_FILE=${ASSET_ABS} -D OUT_C=${ASSET_EMBED_C_OUT} -D SYMBASE=${ASSET_SYMBASE} -D XXD_EXE=${XXD_EXECUTABLE} -P "${SHADER_EMBED_SCRIPT}" DEPENDS "${ASSET_ABS}" "${SHADER_EMBED_SCRIPT}" COMMENT "Building C object ${ASSET_RELATIVE}.o" VERBATIM ) list(APPEND EMBEDDED_OUTPUTS ${ASSET_EMBED_C_OUT}) endforeach() target_sources(${TARGET_NAME} PRIVATE ${EMBEDDED_OUTPUTS}) endfunction()