WebGL много текстур

#javascript #opengl-es #webgl #twgl.js

#javascript #opengl-es #webgl #twgl.js

Вопрос:

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

Моя цель — имитировать слои. Изначально я настраивал каждый слой, используя разные контексты, а затем скомпилировал каждый в окончательный отрисованный холст, но создание текстуры из холста при каждом рендеринге происходило медленно. Затем я использовал Uint8Array для каждого слоя, который содержит данные изображения, и это было намного быстрее, но привело к проблеме, с которой я столкнулся сейчас.

Проблема в том, когда я добавляю более 8 слоев. Если у меня есть 8 слоев и добавить еще один, то первый слой кажется пустым — слой становится пустым. Я попытался перейти от Uint8Array к использованию текстуры для каждого слоя, но проблема все еще сохраняется.

При необходимости я могу предоставить несколько фрагментов кода, но в нескольких файлах много кода, и это немного запутанно, поскольку я пытался это решить. Слои компилируются с использованием двух фреймбуферов для прорисовки взад и вперед, а шейдер обрабатывает математику.

Восемь слоев, рендеринг правильный: Восемь слоев

Девять слоев, разбивает вещи: Девять слоев

Редактировать: Вот некоторый код, и я забыл упомянуть, что я использую вспомогательную библиотеку twgl.

Сначала я настраиваю текстуру слоя:

 this.renderTexture = twgl.createTexture(gl, {
    width: this.width,
    height: this.height,
    target: gl.TEXTURE_2D,
    min: gl.NEAREST,
    max: gl.NEAREST,
    wrap: gl.CLAMP_TO_EDGE
});
  

Я рисую что-то (например, изображение) в framebuffer, а затем обновляю текстуру соответствующего слоя:

 gl.readPixels(0, 0, this.width, this.height, gl.RGBA, gl.UNSIGNED_BYTE, this.buf8);

twgl.setTextureFromArray(gl, this.renderTexture, this.buf8, {
    width: this.width,
    height: this.height
});
  

И, наконец, я превращаю каждый слой в один:

 // create two buffers to ping pong
var blendedFramebufferInfo = [
    twgl.createFramebufferInfo(gl, [{
        src: $this.layers.length === 1 ? null : bottomLayer.buf8,
        width: gl.canvas.width,
        height: gl.canvas.height,
        target: gl.TEXTURE_2D,
        format: gl.RGBA,
        min: gl.NEAREST,
        max: gl.NEAREST,
        wrap: gl.CLAMP_TO_EDGE
    }], gl.canvas.width, gl.canvas.height),

    twgl.createFramebufferInfo(gl, [{
        width: gl.canvas.width,
        height: gl.canvas.height,
        target: gl.TEXTURE_2D,
        format: gl.RGBA,
        min: gl.NEAREST,
        max: gl.NEAREST,
        wrap: gl.CLAMP_TO_EDGE
    }], gl.canvas.width, gl.canvas.height)
];

var layers = [...],
    activeBuffer = 1;

while (layer = layers.shift()) {
    // bind to either buffer or canvas
    twgl.bindFramebufferInfo(gl, layers.length ? blendedFramebufferInfo[activeBuffer] : null);

    // set proper program
    var programInfo = $this.setBlendProgram(layer.blendMode());

    // set uniforms
    twgl.setUniforms(programInfo, {
        u_dst: blendedFramebufferInfo[activeBuffer ? 0 : 1].attachments[0],
        u_src: layer.renderTexture
    });
    // draw
    gl.drawArrays(gl.TRIANGLES, 0, 6);

    // draw to other texture next time around
    activeBuffer = activeBuffer ? 0 : 1;
}
  

Комментарии:

1. Можно посмотреть какой-нибудь код и ваши шейдеры? Трудно точно понять, что у вас происходит здесь на уровне API.

2. Добавлен соответствующий код. Шейдеры очень простые, с четырьмя вершинами и копирующим фрагментом, так что это определенно работает нормально.

3. Если проще объяснить, как это должно быть сделано без twgl, это совершенно нормально. Я бы предпочел даже не использовать библиотеку, но, как я уже сказал, я не слишком много работал с webgl, и его использование показалось мне более простым.

4. Вам нужно вызвать gl.readPixels ? Не могли бы вы просто отобразить текстуру напрямую (прикрепите ее к фреймбуферу). Это будет намного быстрее. Что касается причины сбоя на 8 слоях, из кода, который вы опубликовали до сих пор, ничего не ясно. Можете ли вы привести рабочий пример в вопросе?

5. Я думаю, что, возможно, я слишком усложнил свой код. Я собираюсь попытаться упростить вещи, и я опубликую здесь ответ с обновлением.