Очистка расположения атрибутов в шейдере OpenGL

Есть ли способ перезаписать или очистить местоположение атрибута в OpenGL? Например (я использую lwjgl) я делаю что-то вроде этого:

public void render(int vaoID, int vertexCount, int shaderProgramID){
    GL30.glBindVertexArray(vaoID);

    GL20.glBindAttribLocation(shaderProgramID, 0, "position");
    GL20.glBindAttribLocation(shaderProgramID, 1, "normal");

    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);

    GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertexCount);

    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);

    GL30.glBindVertexArray(0);
}

и после этого я хочу запустить следующий код с тем же ShaderProgramID

public void render(int vaoID, int vertexCount, int shaderProgramID){
    GL30.glBindVertexArray(vaoID);

    //this previously was position
    GL20.glBindAttribLocation(shaderProgramID, 0, "normal");
    //and this was the normal
    GL20.glBindAttribLocation(shaderProgramID, 1, "position");

    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);

    GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertexCount);

    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);

    GL30.glBindVertexArray(0);
}

Как видите, я изменил следующий код:

GL20.glBindAttribLocation(shaderProgramID, 0, "position");
GL20.glBindAttribLocation(shaderProgramID, 1, "normal");

к этому:

GL20.glBindAttribLocation(shaderProgramID, 0, "normal");
GL20.glBindAttribLocation(shaderProgramID, 1, "position");

Но когда я запускаю оба кода,

GL20.glGetAttribLocation(programID, "position");

возвращает 0 вместо 1

Есть ли способ очистить ранее привязанные местоположения, чтобы я мог привязать новые?


person user370001    schedule 29.08.2015    source источник


Ответы (1)


Вы должны повторно связать свою программу после привязки местоположений атрибутов. Это описано в документации для glBindAttribLocation (...) следующим образом:

Имя

glBindAttribLocation — связывает общую вершину индекс атрибута с именованной атрибутивной переменной

C Спецификация

void glBindAttribLocation(программа GLuint, индекс GLuint, const GLchar *имя);

Описание

[...]

Привязки имени переменной атрибута к универсальному индексу атрибута для объекта программы можно явно назначить в любое время, вызвав glBindAttribLocation. Привязки атрибутов не вступают в силу до тех пор, пока не будет вызван glLinkProgram. После успешного связывания объекта программы значения индекса для общих атрибутов остаются фиксированными (и их значения можно запросить ) до тех пор, пока не появится следующая команда связывания.

Любая привязка атрибута, которая происходит после связывания программного объекта, не вступит в силу до следующего связывания программного объекта.

person Andon M. Coleman    schedule 29.08.2015
comment
Спасибо за ответ, все работает. Единственная проблема заключается в том, что мои юниформ-переменные очищаются каждый раз, когда я запускаю glLinkProgram. Есть ли способ сохранить их при сбросе местоположений атрибутов? - person user370001; 29.08.2015
comment
@ user370001: Это поведение не определено спецификацией. Я бы сказал нет. Значения ваших юниформ могут остаться прежними или измениться, нет никакого способа контролировать то, что происходит с данными в программе после повторной компоновки. Как правило, вам все равно не следует часто менять места привязки атрибутов — возможно, вам лучше провести рефакторинг некоторого кода, чтобы избежать необходимости делать это. - person Andon M. Coleman; 29.08.2015
comment
Я хочу сделать это как можно быстрее, поэтому я придумаю другой способ сделать это. В любом случае спасибо за ответ. - person user370001; 29.08.2015
comment
Поместите свою униформу в единый блок, поддерживаемый буферным объектом. Тогда они существуют отдельно от программы (и могут совместно использоваться несколькими программами), и вам просто нужно снова вызвать glUniformBlockBinding при повторном связывании программы. - person Hugh Fisher; 31.08.2015