Прекомпиляция нескольких программ - PullRequest
0 голосов
/ 02 февраля 2019

До сих пор у меня были хорошие успехи в рендеринге в выходную текстуру с использованием входных данных (текстура)

В интересах скорости я хочу, чтобы набор предварительно скомпилированных программ webgl был готов к "использованию"в зависимости от того, что я хочу сделать

возможно ли (псевдокод)

 createProgram #1
 createProgram #2
 createProgram #3
 createProgram #4

1: useProgram #1
2: attach selected frame buffers/uniforms
3: setViewPort (depended on output framebuffer attached texture)
3: drawArrays
4: readPixels

В этот момент я хочу использовать другую программу (например, # 2), что происходит с прикрепленной униформойи буферы для программы # 1 мне нужно очистить их?Могу ли я оставить их на месте и использовать их позже?

Если я выдаю «useProgram # 1», все ли активные униформы и кадровые буферы, которые я выбрал для программы # 1, остаются неизменными ??

1 Ответ

0 голосов
/ 03 февраля 2019

Да, вы можете настроить несколько программ во время инициализации.Это нормальная вещь.

примечания:

Унифицированные местоположения уникальны для каждой программы

Например, давайте сделаем 2 шейдерные программы с одинаковым содержимым и попробуем использоватьединое местоположение из одной программы с другой программой.

const gl = document.querySelector('canvas').getContext('webgl');

const vs = `
void main() {
  // draw a 10 pixel "POINT" in the center of the canvas
  gl_PointSize = 10.0;
  gl_Position = vec4(0, 0, 0, 1);
}
`;

const fs = `
precision mediump float;
uniform vec4 color;
void main() {
  gl_FragColor = color;
}
`;

// make 2 identical programs
// compile shaders, link programs
const p1 = twgl.createProgram(gl, [vs, fs]);
const p2 = twgl.createProgram(gl, [vs, fs]);

// look up color location from first program
const colorLoc = gl.getUniformLocation(p1, 'color');

// try to use colorLoc with second program
gl.useProgram(p2);  // make p2 the current program
gl.uniform4fv(colorLoc, [1, 0, 0, 1]);

console.log('error:', glEnumToString(gl, gl.getError()));

function glEnumToString(gl, v) {
  return Object.keys(WebGLRenderingContext.prototype)
      .filter(k => gl[k] === v)
      .join(' | ');
}
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>

Сбой с INVALID_OPERATION.Вам нужно искать местоположения отдельно для каждой программы

единообразное состояние для каждой программы

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

const gl = document.querySelector('canvas').getContext('webgl');

const vs = `
attribute vec4 position;
void main() {
  // draw a 10 pixel "POINT" in the center of the canvas
  gl_PointSize = 10.0;
  gl_Position = position;
}
`;

const fs = `
precision mediump float;
uniform vec4 color;
void main() {
  gl_FragColor = color;
}
`;

// make 3 identical programs
// compile shaders, link programs, force position to location 0 by calling 
// bindAttribLocation
const p1 = twgl.createProgram(gl, [vs, fs], ['position']);
const p2 = twgl.createProgram(gl, [vs, fs], ['position']);
const p3 = twgl.createProgram(gl, [vs, fs], ['position']);

// look up color location for each program
const colorLocP1 = gl.getUniformLocation(p1, 'color');
const colorLocP2 = gl.getUniformLocation(p2, 'color');
const colorLocP3 = gl.getUniformLocation(p3, 'color');

// set the color uniform on each program
gl.useProgram(p1);
gl.uniform4fv(colorLocP1, [1, 0, 0, 1]);
gl.useProgram(p2);
gl.uniform4fv(colorLocP2, [0, 1, 0, 1]);
gl.useProgram(p3);
gl.uniform4fv(colorLocP3, [0, 0, 1, 1]);

// draw with each program
const positionIndex = 0; 
gl.vertexAttrib2f(positionIndex, -0.5, 0);
gl.useProgram(p1);
gl.drawArrays(gl.POINTS, 0, 1);  // draw 1 point

gl.vertexAttrib2f(positionIndex, 0.0, 0);
gl.useProgram(p2);
gl.drawArrays(gl.POINTS, 0, 1);  // draw 1 point

gl.vertexAttrib2f(positionIndex, 0.5, 0);
gl.useProgram(p3);
gl.drawArrays(gl.POINTS, 0, 1);  // draw 1 point
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>

атрибуты являются частью состояния массива вершин

К каждому включенному атрибуту прикрепляется буфер при вызове vertexAttribPointer

Единицы текстуры - это глобальное состояние.

Какая единица текстуры используется единообразным сэмплером конкретной программы - это состояние программы (это единообразие, то есть состояние программы).Но то, что текстуры на каждом текстурном блоке, является глобальным состоянием.Другими словами, если у вас есть шейдерная программа с

uniform sampler2D foo;

, тогда вы сообщаете этой шейдерной программе, какой текстурный блок использовать с

gl.uniform1i(fooLocation, indexOfTextureUnit);

Но указывайте, является ли каждая текстурная единица глобальнойгосударство.Например, если он был реализован в JavaScript

gl = {
  activeTexture: 0,
  textureUnits: [
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, ... },
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, ... },
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, ... },
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, ... },
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, ... },
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, ... },
    ... MAX_COMBINED_TEXTURE_UNITS ...
  ],
};

, и функции, управляющие текстурами, работают с этими единицами, как это

gl = {
  activeTexture(unitEnum) {
    this.activeTexture = unitEnum - gl.TEXTURE0;
  }
  bindTexture(target, texture) {
    const textureUnit = this.textureUnits[this.activeTexture];
    textureUnit[target] = texture;
  }
  texImage2D(target, ...args) {
    const textureUnit = this.textureUnits[this.activeTexture];
    updateDataToTexture(textureUnit[target], ...args);
  }
}

Текущие привязки кадрового буфера являются глобальным состоянием.

...