我正在尝试在 Vulkan 项目中支持
#include
的 glsl 指令。
据我了解,所需要做的就是正确实现 IncluderInterface 并设置它,我是这样做的:
class NEShaderIncluder : public CompileOptions::IncluderInterface
{
shaderc_include_result* GetInclude(
const char* requested_source,
shaderc_include_type type,
const char* requesting_source,
size_t include_depth)
{
cout << requested_source << endl;
cout << to_string(type) << endl;
cout << requesting_source << endl;
cout << include_depth << endl;
const string name = string(requested_source);
const string contents = ReadFile(name);
auto container = new std::array<std::string, 2>;
(*container)[0] = name;
(*container)[1] = contents;
auto data = new shaderc_include_result;
data->user_data = container;
data->source_name = (*container)[0].data();
data->source_name_length = (*container)[0].size();
data->content = (*container)[1].data();
data->content_length = (*container)[1].size();
cout << "!!!!!!!!!!!!!!!!!!!" << endl;
cout << data->content << endl;
return data;
};
void ReleaseInclude(shaderc_include_result* data) override
{
delete static_cast<std::array<std::string, 2>*>(data->user_data);
delete data;
};
};
CompileOptions SetShaderCompilationOptions()
{
CompileOptions options;
options.SetIncluder(std::make_unique<NEShaderIncluder>());
options.SetGenerateDebugInfo();
return options;
}
然后我像这样编译我的着色器:
Compiler compiler;
CompileOptions options = SetShaderCompilationOptions();
shaderc::SpvCompilationResult result =
compiler.CompileGlslToSpv(source, shader_type, shader_name.c_str(), options);
我添加到该函数中的所有打印语句都可以工作并打印我期望的内容,例如这是最后一个打印:
vec4 BlinnPhong(vec3 pos, vec3 normal, vec3 camera_position)
{
vec4 color = vec4(0);
vec3 l = vec3(1);
vec3 c = vec3(0, 0, 0.7);
vec3 n = normalize(normal);
vec3 e = camera_position - pos;
e = normalize(e);
vec3 h = normalize(e + l);
color = vec4(
c * (vec3(0.1) + 0.9 * max(0, dot(n, l))) +
vec3(0.9) * max(0, pow(dot(h, n), 100)),
1);
return color;
}
但是,shaderrc 似乎并没有取代包含,我从结果对象中收到此错误消息:
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_GOOGLE_include_directive : require
#include "shaders/Example2/phong_lighting.glsl"
layout(location = 0) out vec4 color_out;
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 tex_coord;
layout(location = 2) in vec3 normal;
layout(binding = 1) uniform CameraInfo {
vec3 camera_position;
};
void main()
{
color_out = BlinnPhong(position, normal);
}:
fragment_shader:19: error: 'BlinnPhong' : no matching overloaded function found
fragment_shader:19: error: 'assign' : cannot convert from ' const float' to 'layout( location=0) out highp 4-component vector of float'
我不完全确定我使用的API有什么问题,而且我也无法在网上找到示例来交叉引用。
我怀疑必须事先调用
PreprocessGlsl
,但我不确定你应该如何链接预处理和编译。
问题是,除了设置包含之外,您还应该调用预处理阶段,正确的调用站点如下所示:
shaderc::PreprocessedSourceCompilationResult pre_result =
compiler.PreprocessGlsl(source, shader_type, shader_name.c_str(), options);
Assert(
pre_result.GetCompilationStatus() == shaderc_compilation_status_success,
"Preprocess failed for file " + source + ":\n" + pre_result.GetErrorMessage());
string pre_passed_source(pre_result.begin());
shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(
pre_passed_source, shader_type, shader_name.c_str(), options);
Assert(
result.GetCompilationStatus() == shaderc_compilation_status_success,
pre_passed_source + ":\n" + result.GetErrorMessage());
我认为这不是包含的问题,而是您的代码的问题。 include 中的
BlinnPhong
接受 3 个参数,但调用它时只传递 2 个参数。这与第一条错误消息相符。
您忘记将包含器添加到编译器选项中,因此它根本没有被使用。
options.SetIncluder(std::make_unique<NEShaderIncluder>());
这样做就足够了,预处理不是必需的,而是第二种可能性。