这个问题已经以不同的方式被问了多次。我的问题针对OpenGL 2.0/GLSL 1.10及更高版本,以及与OpenGL ES 2.0及其支持的GLSL:版本的潜在兼容性
建议使用哪些C/C++API将多个文件组合到一个着色器源中以传递到glShaderSource。
例如,如果我有3个文件A.frag、B.frag、C.frag,它们的内容如下:
/* A.frag */
struct A
{
vec3 val;
};
/* B.frag */
struct B
{
vec3 val;
};
/* C.frag */
void main() {
struct A a;
a.val = vec3(1.0, 1.0, 1.0);
struct B b;
b.val = vec3(1.0, 1.0, 1.0);
float f = dot(a.val, b.val);
}
什么现有的工具可以让我将所有三个文件的内容合并到一个源中,以便进行编译?考虑到每个着色器源可能要复杂得多。
如果您查看函数规范glShaderSource
:
void glShaderSource(GLuint shader,
GLsizei count,
const GLchar **string,
const GLint *length);
您可以看到第三个参数是字符串数组(chars)的数组。
我写了一个c++类来实现你想要做的事情。我发现最好的方法是分别加载文件,然后将不同的着色器源代码放入双指针中,最后将其传递给函数glShaderSource。
例如:
GLchar** fragment_code; // This must be initialized
GLint* fragment_char_count;
void LoadFragment()
{
//assuming fragment_filepath a vector<string> containing different shader filepaths
for (size_t i = 0; i < fragment_filepath.size(); i++)
{
Load(fragment_filepath[i], fragment_code[i], fragment_char_count[i]);
}
}
// source_path is the shader file path in the filesystem
// output will contain the source code of the shader being loaded
// fragment_char_count will contain the number of char for the shader being loaded
static void Load(string source_path, GLchar*& output,GLint& fragment_char_count)
{
string return_code;
try
{
// Open files
ifstream vShaderFile(source_path);
stringstream vShaderStream;
// Read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
// Convert stream into GLchar array
return_code = vShaderStream.str();
}
catch(exception e)
{
cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ: " << source_path << endl;
}
fragment_char_count = return_code.length() ;
output = new GLchar[count + 1];
std::size_t length = return_code.copy(output,fragment_char_count,0);
output[length]= ' ';
}
// eventually when you compile you pass to glShaderSource the fragment_id, the number of shader program you are loading (fragment_filepath.size()), the double pointer of char containing the different source codes (fragment_code) and an array representing the char count for each source (fragment_char_count)
void CompileFragment()
{
glShaderSource(fragment_shader_id, fragment_filepath.size(), fragment_code, fragment_char_count);
glCompileShader(d_vertex_shader);
}
这不是很简单,不幸的是OpenGL仍然是用纯C编写的。然而,在这里你可以找到整个类实现的要点。通过这样做,可以将多个着色器编译并链接在一起(当然,只要它们都是相同类型)。
希望能有所帮助。