You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CMake重构VS2022项目时无法读取.glsl文件求助

解决CMake项目中GLSL着色器文件找不到的问题

问题根源在于:程序运行时会从当前工作目录查找vShader.glsl和fShader.glsl,但这些文件实际存放在EngineLibray/Graphics/Shader目录下,编译过程中不会自动拷贝到可执行文件的输出目录,导致运行时找不到文件。以下是三种可行的解决方案:


方案1:将GLSL文件自动复制到可执行文件输出目录

修改Shader模块的CMakeLists.txt,添加文件拷贝逻辑,编译时自动将着色器文件同步到可执行文件的输出目录:

# 定义着色器文件路径
set(SHADER_FILES
    "${CMAKE_CURRENT_SOURCE_DIR}/vShader.glsl"
    "${CMAKE_CURRENT_SOURCE_DIR}/fShader.glsl"
)

# 将着色器文件复制到可执行文件输出目录
foreach(SHADER ${SHADER_FILES})
    get_filename_component(SHADER_NAME ${SHADER} NAME)
    configure_file(${SHADER} "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${SHADER_NAME}" COPYONLY)
endforeach()

# 原有Shader库定义代码保持不变
set(LIBRARY_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/include/Shader.h")
set(LIBRARY_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/src/Shader.cpp")
add_library(Shader STATIC
    ${LIBRARY_HEADER}
    ${LIBRARY_SOURCE}
)

target_include_directories(Shader 
    PUBLIC
        include/
    PRIVATE
        src/
)

target_link_libraries(Shader PRIVATE ExternalLibs)

这种方式适合需要随时修改着色器文件、无需重新编译程序的场景。


方案2:通过CMake传递绝对路径加载着色器

直接在代码中使用着色器文件的绝对路径,避免文件拷贝操作:

  1. 修改Shader模块的CMakeLists.txt,通过编译宏传递文件绝对路径:
set(LIBRARY_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/include/Shader.h")
set(LIBRARY_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/src/Shader.cpp")
add_library(Shader STATIC
    ${LIBRARY_HEADER}
    ${LIBRARY_SOURCE}
)

# 传递着色器文件的绝对路径给代码
target_compile_definitions(Shader
    PRIVATE
        VSHADER_PATH="${CMAKE_CURRENT_SOURCE_DIR}/vShader.glsl"
        FSHADER_PATH="${CMAKE_CURRENT_SOURCE_DIR}/fShader.glsl"
)

target_include_directories(Shader 
    PUBLIC
        include/
    PRIVATE
        src/
)

target_link_libraries(Shader PRIVATE ExternalLibs)
  1. 修改Renderer.cpp中的代码,使用编译宏定义的路径:
const char* Render::VertShader()
{
    return VSHADER_PATH;
}

const char* Render::FragShader()
{
    return FSHADER_PATH;
}

void Render::CreateShader()
{
    pShader = new Shader();
    pShader->CreateFromFile(VertShader(), FragShader());
    ShaderList.push_back(pShader);
}

这种方式无需拷贝文件,直接引用源文件路径,适合不需要动态修改着色器的场景。


方案3:将GLSL文件嵌入到二进制文件中

把着色器内容编译为C++字符串,直接嵌入到静态库/可执行文件中,消除外部文件依赖:

  1. 修改Shader模块的CMakeLists.txt,添加自定义命令生成包含着色器内容的头文件:
# 自定义函数:将GLSL文件转换为C++字符串头文件
function(compile_shader SHADER_FILE OUTPUT_VAR)
    file(READ ${SHADER_FILE} SHADER_CONTENTS)
    # 转义字符串中的特殊字符
    string(REPLACE "\"" "\\\"" SHADER_CONTENTS "${SHADER_CONTENTS}")
    string(REPLACE "\n" "\\n\"\n\"" SHADER_CONTENTS "${SHADER_CONTENTS}")
    # 生成头文件内容
    set(SHADER_HEADER "static const char* ${OUTPUT_VAR} = \"${SHADER_CONTENTS}\";")
    file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_VAR}.h" "${SHADER_HEADER}")
endfunction()

# 生成两个着色器的头文件
compile_shader("${CMAKE_CURRENT_SOURCE_DIR}/vShader.glsl" VERT_SHADER_SRC)
compile_shader("${CMAKE_CURRENT_SOURCE_DIR}/fShader.glsl" FRAG_SHADER_SRC)

# 原有Shader库定义代码
set(LIBRARY_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/include/Shader.h")
set(LIBRARY_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/src/Shader.cpp")
add_library(Shader STATIC
    ${LIBRARY_HEADER}
    ${LIBRARY_SOURCE}
)

# 添加生成头文件的目录到包含路径
target_include_directories(Shader 
    PUBLIC
        include/
    PRIVATE
        src/
        ${CMAKE_CURRENT_BINARY_DIR}
)

target_link_libraries(Shader PRIVATE ExternalLibs)
  1. 修改Renderer.cpp,直接使用生成的字符串(需同步修改Shader类的接口,新增接受字符串的创建方法,比如CreateFromString):
#include "VERT_SHADER_SRC.h"
#include "FRAG_SHADER_SRC.h"

const char* Render::VertShaderSource()
{
    return VERT_SHADER_SRC;
}

const char* Render::FragShaderSource()
{
    return FRAG_SHADER_SRC;
}

void Render::CreateShader()
{
    pShader = new Shader();
    pShader->CreateFromString(VertShaderSource(), FragShaderSource());
    ShaderList.push_back(pShader);
}

这种方式适合需要完全消除外部文件依赖的场景,程序发布时无需携带着色器文件。

内容的提问来源于stack exchange,提问作者GloriousDemonFist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:42:16