glGetUniformLocation returns -1 用于 USED 变量,优化地狱
glGetUniformLocation returns -1 for USED variable, Hell with optimization
我知道如果某些 uniform
变量没有对管道的输出做出积极贡献,它会被优化并且应该 return -1。考虑下面的片段着色器。
const char fShader[] = "precision mediump float; \n"
"uniform float uGlobalTime; \n"
"const int iMaxIterations = 6; \n"
"float fCircleSize = 1.0 / (3.0 * pow(2.0, float(iMaxIterations))); \n"
"vec2 Rotate(vec2 uv, float a) \n"
"{ \n"
"return vec2(uv.x * cos(a) - uv.y * sin(a), uv.y * cos(a) + uv.x * sin(a)); \n"
"} \n";
"void main() \n"
"{ \n"
"vec2 uv = vec2(1280.0, 720.0); \n"
"uv = -0.5 * (uv - 2.0 * gl_FragCoord.xy) / uv.x; \n"
"uv = Rotate(uv, uGlobalTime); \n"
"uv *= sin(uGlobalTime) * 0.5 + 1.5; \n"
"float s = 0.3; \n"
"for(int i = 0 ; i < iMaxIterations; ++i) \n"
"{ \n"
"uv = abs(uv) - s; \n"
"uv = Rotate(uv, uGlobalTime); \n"
"s = s / 2.0; \n"
"} \n"
"float c = length(uv) > fCircleSize ? 0.0:1.0; \n"
"gl_FragColor = vec4(c * uGlobalTime, c * uGlobalTime, c * uGlobalTime, 1.0); \n"
"} \n";
这真诚地尝试在多个位置使用通过的制服,并在最终输出颜色中使用。但我仍然得到 -1 作为 return 值。虽然没有错误。我也不认为我这边有什么问题。
优化完成,我确定。我没有检查现役制服,只有 2 件。我正在使用 3。但是为什么在地球上......编译器是盲目的......??
我可以通过使用属性绕过,但我为什么要这样做?
编辑
请同时查看我的顶点着色器
const char vShader[] = "attribute vec3 vPosition; \n"
"uniform mat4 uMVMatrix; \n"
"uniform mat4 uPMatrix; \n"
"void main(void) \n"
"{ \n"
"gl_Position = uPMatrix * uMVMatrix * vec4(vPosition, 1.0); \n"
"} \n";
我列出了我自己的解决方法:
在适当位置的顶点着色器中添加 3 行:
"attribute float vGlobalTime \n"
"varying float globalTime; \n"
"globalTime = vGlobalTime; \n"
和片段着色器中的 1 个新行:
"varying float globalTime; \n"
并且现在在我之前使用 uGlobalTime
的所有地方使用 globalTime
PS:我没有测试过这个;但我看不出它为什么不起作用的任何理由。
片段着色器 C++ 源字符串定义的第 7 行末尾有一个分号。
const char* source =
"line 1"
"line 2"; // <- semicolon intended?
"line 3+ ignored"; // <- lose string constant which is never assigned to anything
这会导致片段着色器的整个主要功能被跳过,甚至根本不应该 link。 Did you check for errors after linking your program?
考虑将您的着色器代码外包到外部文件中,这样可以防止出现此类拼写错误,并且无需在每次更改着色器时都重新编译您的应用程序。
bool Shader::compileFromFile(const std::string& filename)
{
std::ifstream stream(filename, std::ios_base::in);
if (!stream.is_open())
return false;
std::string source{std::istreambuf_iterator<char>(stream),
std::istreambuf_iterator<char>()};
return compile(source);
}
我知道如果某些 uniform
变量没有对管道的输出做出积极贡献,它会被优化并且应该 return -1。考虑下面的片段着色器。
const char fShader[] = "precision mediump float; \n"
"uniform float uGlobalTime; \n"
"const int iMaxIterations = 6; \n"
"float fCircleSize = 1.0 / (3.0 * pow(2.0, float(iMaxIterations))); \n"
"vec2 Rotate(vec2 uv, float a) \n"
"{ \n"
"return vec2(uv.x * cos(a) - uv.y * sin(a), uv.y * cos(a) + uv.x * sin(a)); \n"
"} \n";
"void main() \n"
"{ \n"
"vec2 uv = vec2(1280.0, 720.0); \n"
"uv = -0.5 * (uv - 2.0 * gl_FragCoord.xy) / uv.x; \n"
"uv = Rotate(uv, uGlobalTime); \n"
"uv *= sin(uGlobalTime) * 0.5 + 1.5; \n"
"float s = 0.3; \n"
"for(int i = 0 ; i < iMaxIterations; ++i) \n"
"{ \n"
"uv = abs(uv) - s; \n"
"uv = Rotate(uv, uGlobalTime); \n"
"s = s / 2.0; \n"
"} \n"
"float c = length(uv) > fCircleSize ? 0.0:1.0; \n"
"gl_FragColor = vec4(c * uGlobalTime, c * uGlobalTime, c * uGlobalTime, 1.0); \n"
"} \n";
这真诚地尝试在多个位置使用通过的制服,并在最终输出颜色中使用。但我仍然得到 -1 作为 return 值。虽然没有错误。我也不认为我这边有什么问题。
优化完成,我确定。我没有检查现役制服,只有 2 件。我正在使用 3。但是为什么在地球上......编译器是盲目的......?? 我可以通过使用属性绕过,但我为什么要这样做?
编辑
请同时查看我的顶点着色器
const char vShader[] = "attribute vec3 vPosition; \n"
"uniform mat4 uMVMatrix; \n"
"uniform mat4 uPMatrix; \n"
"void main(void) \n"
"{ \n"
"gl_Position = uPMatrix * uMVMatrix * vec4(vPosition, 1.0); \n"
"} \n";
我列出了我自己的解决方法:
在适当位置的顶点着色器中添加 3 行:
"attribute float vGlobalTime \n"
"varying float globalTime; \n"
"globalTime = vGlobalTime; \n"
和片段着色器中的 1 个新行:
"varying float globalTime; \n"
并且现在在我之前使用 uGlobalTime
globalTime
PS:我没有测试过这个;但我看不出它为什么不起作用的任何理由。
片段着色器 C++ 源字符串定义的第 7 行末尾有一个分号。
const char* source =
"line 1"
"line 2"; // <- semicolon intended?
"line 3+ ignored"; // <- lose string constant which is never assigned to anything
这会导致片段着色器的整个主要功能被跳过,甚至根本不应该 link。 Did you check for errors after linking your program?
考虑将您的着色器代码外包到外部文件中,这样可以防止出现此类拼写错误,并且无需在每次更改着色器时都重新编译您的应用程序。
bool Shader::compileFromFile(const std::string& filename)
{
std::ifstream stream(filename, std::ios_base::in);
if (!stream.is_open())
return false;
std::string source{std::istreambuf_iterator<char>(stream),
std::istreambuf_iterator<char>()};
return compile(source);
}