如何实际地将GLSL着色器与您的C++软件一起发布

68

在OpenGL初始化期间,程序应该执行类似以下的操作:

<Get Shader Source Code>
<Create Shader>
<Attach Source Code To Shader>
<Compile Shader>

获取源代码可能就像将其放入字符串中一样简单: (示例来自SuperBible,第6版)

static const char * vs_source[] =
{
    "#version 420 core                             \n"
    "                                              \n"
    "void main(void)                               \n"
    "{                                             \n"
    "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);   \n"
    "}                                             \n"
};

问题在于直接在字符串中编辑、调试和维护GLSL着色器很困难。因此,从文件中获取源代码的字符串对于开发来说更加容易:

std::ifstream vertexShaderFile("vertex.glsl");
std::ostringstream vertexBuffer;
vertexBuffer << vertexShaderFile.rdbuf();
std::string vertexBufferStr = vertexBuffer.str();
// Warning: safe only until vertexBufferStr is destroyed or modified
const GLchar *vertexSource = vertexBufferStr.c_str();

现在的问题是如何将着色器与程序一起传输?事实上,将源代码与应用程序一起传输可能会成为问题。 OpenGL支持“预编译二进制着色器”,但是Open Wiki指出:

程序二进制格式不应被传输。 不合理的是期望不同的硬件供应商接受相同的二进制格式。 不合理的是期望来自同一供应商的不同硬件接受相同的二进制格式。 [...]

如何实际地将GLSL着色器与C++软件一起传输?


2
我个人会将源文件保存在着色器目录中,并根据需要将它们加载到程序中的字符串中。 - Tim Seguine
3
它们通常存储在单独的文件中。如果你不希望用户玩弄它们,虚拟文件系统是一个不错的选择。 - Bartek Banachewicz
8
只需将着色器作为文件发送即可。这是每个应用程序的做法。甚至大多数AAA游戏都有它们的着色器以某种方式作为直接可用的文件。 - datenwolf
2
即使您将其捆绑在可执行文件中,它仍然是纯文本,并且很容易被发现。 - n0rd
11个回答

-1
在C99/C11中,您可以通过两个简单的步骤来完成它。
## Bash build script:

## STEP #1: Convert your [C99/C11] code to GLSL by quoting it:

    awk 'NF { print "\""$0"\\""n""\""}' GLSL_AS_C99.C11 > QUOTED.TXT

## STEP #2: Compile your project:

    gcc -x c -c MY_PROJECT_FILE.C11 -o object_file.o -std=c11 -m64
    gcc -o EXE.exe object_file.o
    rm object_file.o
    ./EXE.exe
    rm EXE.exe

是的。这还有更多细节。你必须以一种通用风格编写你的C99代码,以便它也可以编译为GLSL。例如:

#ifdef THIS_IS_BEING_COMPILED_AS_OPEN_GL_SHADER_CODE
    #define I32 int
#endif
#ifdef THIS_IS_BEING_COMPILED_AS_C99_CODE
    #define I32 uint32_t
#endif

使用C99编写的代码可以轻松地剪切并粘贴到GLSL着色器代码中,而不会出现任何问题。它还允许您对GLSL着色器代码进行单元测试。 要包含由AWK命令字符串化的代码,请执行以下操作:

//:AAC2020_PAINT5D_DEFAULT_001:==============================://
const char* AAC2020_PAINT5D_DEFAULT_001=( //:////////////////://
//://////////////////////////////////////////////////////////://
"#version 330 core                           \n"//://////////://
"#define AAC2020_MACRO_THIS_IS_OPEN_GL (1)   \n"//://////////://
//://////////////////////////////////////////////////////////://
//|Everything Below Is Cut+Pasted From       |////://////////://
//|The C99 File: P5D_OGL._                   |////://////////://
//://////////////////////////////////////////////////////////://

    #include "../QUOTED.TXT"
                                                
); //:///////////////////////////////////////////////////////://
//:==============================:AAC2020_PAINT5D_DEFAULT_001://

如果您熟悉C代码和bash脚本,那应该足以解释它。但如果您需要更多的解释,我在YouTube上拍摄了一个30分钟的演示和解释视频。

https://www.youtube.com/watch?v=kQfSL4kv5k0&list=PLN4rUakF78aCdRxjMU8_JBGAKIrtt_7N5&index=115

如果您更喜欢操作代码... 这里是我的游戏引擎构建,使用了这个系统。打开 AAC2020.SH 构建脚本,找到 "awk" 命令并从那里开始倒推。

https://github.com/KanjiCoder/AAC2020

与问题相关的其他文件包括:

  1. P5D1OGL.FRA._ <-- 可以作为GLSL运行并进行单元测试的C99源代码
  2. P5D1OGL.FRA.STRING._ <-- 由awk命令引用的P5D1OGL.FRA._。
  3. P5D_001._ <-- 包含在const char*中嵌入到exe中的P5D1OGL.FRA.STRING._
  4. POLYOGL.D._ <-- OpenGL Polyfills .D(数据/结构)
  5. POLYOGL.F._ <-- OpenGL Polyfills .F(函数)

或者,如果您收听我的twitch直播并请求亲自概述我如何做到这一点,我可以给您展示实时演示和进一步解释。

www.twitch.com/kanjicoder

您也可以通过电子邮件联系我:HeavyMetalCookies@Gmail.com 我目前35岁,现在是2021年。如果我没有回复, 那么要么是我已经去世了,要么是太出名了无法回答,或者两者兼而有之。 让读者自己去猜测是哪一种情况。

- 约翰·马克


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接