在GLSL中外部定义预处理器宏

rio*_*oki 21 opengl preprocessor glsl

GLSL有一个完整的C风格预处理器.唯一不起作用的是#include.其中一个很棒的功能是,您可以使用#ifdef注释掉函数,从而创建一个着色器,如果不使用某些特征,可以将其稀疏.

我的问题是:

有没有办法从C代码定义宏?

使用openGL接口似乎无法做到这一点.快速入侵是在代码加载表单文件之前使用#define FOO添加几行.但它似乎有点倒退.

Bah*_*bar 25

您实际上不需要将其添加到您加载的代码中.这就是glShaderSourceARB API中有多个字符串的原因.

您正在寻找以下内容:

char *sources[2] = { "#define FOO\n", sourceFromFile };
glShaderSourceARB(shader, 2, sources, NULL);
Run Code Online (Sandbox Code Playgroud)

  • -1:是一个*可怕的想法*.着色器中的第一件事需要是`#version`声明.通过像这样随意地添加东西,你就不可能做到这一点.因此,您将默认使用GLSL版本1.10,这是非常古老的. (24认同)
  • @Luca:除非您有使用不同版本的GLSL的创新理念.然后你必须在你的代码中更改它,而不是你的着色器.这意味着您的着色器不能再独立. (10认同)
  • 这是一个有效的解决方案,但不比预先添加源代码好多少. (4认同)
  • @NicolBolas这足够了`sources [3] == {"#version 330 core \n","#define FOO \n,..."`使它成为一个_好主意_. (4认同)
  • 好吧,这取决于你所追求的.这样可以防止一些额外的内存分配和复制(这就是为什么我会考虑前置解决方案hacky).什么看起来更好,为什么? (2认同)

joh*_*n d 7

这是我用来避免#version问题的方法.它是Java,并没有针对perfo进行优化,但它完美地运行:

// extract shader sourcecode from file
StringBuilder shaderSource = Tools.readTextRessource(shaderSrcFile.url);

// apply defined values
int versionIndex = shaderSource.indexOf("#version");
if(versionIndex == -1) err("missing #version xxx in shader "+shaderSrcFile.name());
int defineInsertPoint = shaderSource.indexOf("\n", versionIndex)+1;

for (int i = defined.size() - 1; i >= 0; --i)
    shaderSource.insert(defineInsertPoint, "#define " + defined.get(i) + "\n");
Run Code Online (Sandbox Code Playgroud)