GLSL: о причине, по которой glGetUniformLocation() может вернуть -1 (комментарии)
Это сообщение сгенерировано автоматически.
А не проще ли проверять, не равен ли location минус единице, и не вызывать glUniform* для него? Я просто написал свои функции установки юниформа в классе шейдера, которые делают эту проверку, и радуюсь.
Проблема на ровном месте. :)
1) В доке написано почему glGetUniformLocation может быть -1:
This function returns -1 if name does not correspond to an active uniform variable in program
2) Не является ошибкой вызов glUniform с location -1. О чём опять же написано в доке:
If location is equal to -1, the data passed in will be silently ignored and the specified uniform variable will not be changed.
Автор видимо предпочитает потратить кучу времени на изобретение велосипеда, вместо того, чтобы потратить одну минуту на чтение доки.
Вот так я делаю. Всё без каких-то там проверок нормально идет.
GL.CreateProgram = function(identifier, uniforms, attribs, textures) { var p = gl.createProgram(); var program = { identifier: identifier, program: p, attribs: [] }; var vsh = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vsh, document.getElementById('vsh' + identifier).text); gl.compileShader(vsh); if (gl.getShaderParameter(vsh, gl.COMPILE_STATUS) !== true) Sys.Error('Error compiling shader: ' + gl.getShaderInfoLog(vsh)); var fsh = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fsh, document.getElementById('fsh' + identifier).text); gl.compileShader(fsh); if (gl.getShaderParameter(fsh, gl.COMPILE_STATUS) !== true) Sys.Error('Error compiling shader: ' + gl.getShaderInfoLog(fsh)); gl.attachShader(p, vsh); gl.attachShader(p, fsh); gl.linkProgram(p); if (gl.getProgramParameter(p, gl.LINK_STATUS) !== true) Sys.Error('Error linking program: ' + gl.getProgramInfoLog(p)); gl.useProgram(p); var i; for (i = 0; i < uniforms.length; ++i) program[uniforms[i]] = gl.getUniformLocation(p, uniforms[i]); for (i = 0; i < attribs.length; ++i) { program.attribs[program.attribs.length] = attribs[i]; program[attribs[i]] = gl.getAttribLocation(p, attribs[i]); } for (i = 0; i < textures.length; ++i) { program[textures[i]] = i; gl.uniform1i(gl.getUniformLocation(p, textures[i]), i); } GL.programs[GL.programs.length] = program; return program; }; GL.UseProgram = function(identifier) { var i, j; var program = GL.currentprogram; if (program != null) { if (program.identifier === identifier) return program; for (i = 0; i < program.attribs.length; ++i) gl.disableVertexAttribArray(program[program.attribs[i]]); } for (i = 0; i < GL.programs.length; ++i) { program = GL.programs[i]; if (program.identifier === identifier) { GL.currentprogram = program; gl.useProgram(program.program); for (j = 0; j < program.attribs.length; ++j) gl.enableVertexAttribArray(program[program.attribs[j]]); return program; } } }; GL.UnbindProgram = function() { if (GL.currentprogram == null) return; var i; for (i = 0; i < GL.currentprogram.attribs.length; ++i) gl.disableVertexAttribArray(GL.currentprogram[GL.currentprogram.attribs[i]]); GL.currentprogram = null; };
ALPINE
можно, например, вписав вот такую строчку в конец фраргментного шейдера:
gl_FragColor.r += 0.000001*v_uv[0];
Она не окажет влияния на картинку, зато не даст компилятору съесть переменную. А ближе к финальной версии неиспользуемых переменных в шейдере само собой быть не должно .
Мда... такой нелепый "хинт" - загружать шейдер вычислениями с неиспользуемой переменной - мне даже в голову не приходил :-|.
В моём "движке" ошибка выводится только для тех uniform'ов, которые должны быть железно в шейдере.
Остальные - просто засоряют лог warning'ами в дебаге (что несколько утомительно, когда одна шейдерная программа линкуется из разных кусочков и в некоторых комбинациях часть uniform'ов отбрасывается).
ALPINE
Это не наш метод :)
Я так и в HLSL делаю, когда чтото тестирую.
> Автор видимо предпочитает потратить кучу времени на изобретение велосипеда,
> вместо того, чтобы потратить одну минуту на чтение доки.
Автор предпочитает потратить кучу времени на выяснение обстоятельства, почему glGetError не пустой. А судя по
will be silently ignored
должен быть пустой. Из предположений - Valve не до конца допилили драйвер nVidia в линуксе.
> Мда... такой нелепый "хинт"
Первое, что пришло в голову. Есть идеи получше? Говорите, приму к сведению и допишу.
> А не проще ли проверять, не равен ли location минус единице
Не проще, т.к. если наткнусь на -1, то надо будет еще и отменять вызовы glEnableVertexAttribArray и так далее.
Хех, -1 выбрасывает, если запрашиванных переменных в шейдере нету. А нету их по трем причинам: 1) Шейдер не сбилдился и там нету никаких переменных вообще, в том числе и этой. 2) Шейдер сбилдился но этой переменной там нету. 3) Когда шейдер билдился эта переменная оказалась не использованной и ее выбросили ради оптимизации, соответственно ее там нету. И того "о причине, по которой glGetUniformLocation() может вернуть -1": исключительно тогда когда запрашиваемой переменной нету. А причины по которым она все же есть но куда-то пропала, можно описать отдельно. ИМХО.
Cyber_Wanderer
> если запрашиванных переменных в шейдере нету. А нету их по трем причинам
А в первых двух случаях ошибок разве никаких нет? В первой уж точно должна быть - статус соответствующий будет, валидация не пройдёт. Про второй случай вот не знаю, но никто в здравом уме не будет искать отсутствующую переменную, так ведь? А вот в третьем случае однозначно не скажешь, что переменная отсутствует - ты её определил и вроде как даже использовал. А её нет. Именно из-за этого ситуация несколько сбивающая с толку и именно из-за этого я о ней и рассказал.
ALPINE
> А вот в третьем случае однозначно не скажешь, что переменная отсутствует - ты
> её определил и вроде как даже использовал. А её нет.
Ты противоречивые вещи говоришь.
Если переменная используется, то она будет. Её нет, потому что она не используется.
Не может быть ситуации, когда ты используешь переменную, а её нет.
Под использованием естественно подразумеваю влияние на вычисления.
Executor
> Под использованием естественно подразумеваю влияние на вычисления.
Так я же и пишу - во время экспериментов с шейдером не углядел, что результат вычислений я случайно перезаписал константой (см. пример кода фрагментного шейдера в начале статьи). Да, факт перезаписи имеет место, да, на вычисления переменная уже не влияет. Но это не очень-то и очевидно во время работы над шейдером (комментирования кусков кода и т.д.). Далеко не сразу можно сообразить, откуда внезапно в лог вывалилось куча ошибок при том, что картинка отображается корректная.
ALPINE
> внезапно в лог вывалилось куча ошибок
Каких ошибок?
> Не является ошибкой вызов glUniform с location -1.
UPD: Ты же сам пишешь:
> в моём случае (Linux, nVidia, последний 310-й драйвер) Info Log пустой
А уже оказывается логи с портянками ошибок внезапно появились.
Чем тебе легче будет, что вместо -1 на неиспользуемую переменную получишь локейшен к примеру 8? Аналогично программа как работала, так и будет работать. Смысла в этих бубнах нету.
Executor
> Каких ошибок?
При выполнении
glVertexAttribPointer(a_uv, 4, GL_FLOAT, GL_FALSE, 12 * sizeof(float), data + 4 );
получаю GL_INVALID_VALUE, поскольку a_uv = -1.
ALPINE
> получаю GL_INVALID_VALUE, поскольку a_uv = -1.
э...
Тема в архиве.