Да, вы можете настроить несколько программ во время инициализации.Это нормальная вещь.
примечания:
Унифицированные местоположения уникальны для каждой программы
Например, давайте сделаем 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);
}
}
Текущие привязки кадрового буфера являются глобальным состоянием.