Какой минимальный необходимый код для изменения шейдера WebGL во время выполнения? - PullRequest
1 голос
/ 29 марта 2019

Предположим, я создал программу WebGL, подключил несколько начальных шейдеров, связал программу, проверил и через некоторое время я хочу изменить источник одного из подключенных шейдеров.

Должен ли я создать новую программу WebGL с gl.createProgram(), или я могу просто повторно использовать ее и прикрепить шейдеры?

Я немного смущен этим, потому что есть несколько способовcall:

gl.shaderSource(shader, source);
gl.compileShader(shader);
gl.attachShader(program, shader);
gl.linkProgram(program);
gl.validateProgram(program);

Какие из них необходимы для простой модификации одного из шейдеров в программе?Я предполагаю, что связывание обязательно.Нужно ли создавать новый экземпляр шейдера, или я могу использовать экземпляр повторно и использовать gl.shaderSource() для передачи в новый источник?Нужно ли прикреплять новый / старый шейдер к программе.Стоит ли отсоединять старый шейдер от программы?

Ответы [ 2 ]

2 голосов
/ 29 марта 2019

Вам не нужно создавать новые шейдеры.Вам нужно позвонить gl.shaderSource, чтобы загрузить новый GLSL, а затем gl.compileShader и gl.linkShader.

Это сложная часть спецификации.Что вы пытаетесь сделать?

Если ссылка не работает с вашей программой, программа больше не используется.Если ссылка установлена ​​успешно, у вас фактически есть новая программа, и вам нужно искать все новые атрибуты и единообразные местоположения.

Вы можете создавать новые шейдеры, если хотите, и присоединять их к существующей программе.Перед тем, как прикрепить новые шейдеры, вам нужно отсоединить старые с gl.detachShader(prg, oldShader)

, но вы не уверены, что это полезно, но вы можете думать о внутреннем состоянии WebGLProgram, как это

class WebGLProgram {
   Shader vertexShader;
   Shader fragmentShader;

   // status from last time you called gl.linkProgram
   int linkStatus;

   // message from last time you called gl.linkProgram  
   string infoLog;

   // internal program created by last SUCCESSFUL linkProgram
   Program validProgram; 
}

class Program {
  map<string, int> attribLocations;
  map<string, WebGLUniformLocation> uniformLocations;
  GPUProgramCode compiledProgram
}

class Shader {
  string src;

  // status from last time you called gl.compileShader
  int compileStatus;

  // message from last time you called gl.compileShader  
  string infoLog;

  // internal shader created from last successful compile
  GPUShaderCode compiledShader;
}

.единственное, что имеет значение при рендеринге, это то, что validProgram на WebGLProgram имеет действующую программу.Так, например,

const prg = gl.createProgram();
gl.attachShader(prg, validCompiledVertexShader);
gl.attachShader(prg, validCompiledFragmentShader);
gl.linkProgram(prg);   

// our imaginary prg.validProgram now has a valid program

gl.detachShader(prg, validCompiledVertexShader);
gl.detachShader(prg, validCompiledFragmentShader);
gl.deleteShader(validCompiledVertexShader);
gl.deleteShader(validCompiledFragmentShader);

Это совершенно правильный способ использования шейдеров.Им нужно только остаться достаточно долго, чтобы позвонить linkProgram.

2 голосов
/ 29 марта 2019

Нет необходимости создавать новый шейдер или программный объект, если вы счастливы заменить содержимое существующих объектов. Если вы заменяете содержимое существующих объектов, тогда минимальный набор:

gl.shaderSource(shader, source);
gl.compileShader(shader);
// gl.attachShader(program, shader);
gl.linkProgram(program);

т.е. вам не нужно прикреплять объект шейдера к программе, потому что он уже подключен, но вам нужно делать все остальное.

Нужно ли создавать новый экземпляр шейдера, или я могу повторно использовать экземпляр и использовать gl.shaderSource () для передачи нового источника?

Либо будет работать.

Нужно ли присоединять новый / старый шейдер к программе.

Если вы создаете новый шейдерный объект, тогда да, очевидно, его необходимо будет присоединить к программному объекту, иначе он не будет использоваться в программе.

Стоит ли отсоединять старый шейдер от программы?

Да; Вы получите ошибку GL_INVALID_OPERATION, если попытаетесь подключить шейдер, если он уже подключен в этом месте типа шейдера.

Некоторые общие замечания:

  • Повторно используемый программный объект будет продолжать отражать поведение старого шейдера, пока вы не вызовете linkProgram.
  • Местоположение новой формы и привязок атрибутов может измениться в новой программе, даже если они имеют одинаковые имена. Используйте либо статические привязки, либо запрос после ссылки.
...