WebGL drawBuffer выводит черные текстуры - PullRequest
0 голосов
/ 13 января 2020

Я пытаюсь написать простую многопроходную программу webgl с помощью drawBuffers. Я создаю 2 текстуры drawBuffer и присваиваю им цвет в фрагменте ShaderPass1. Texture1 должен быть зеленым, а Texture2 должен быть коричневым. Затем я передаю эти текстуры как форму для фрагмента ShaderPass2, который использует цвет текстуры Texture1 для визуализации прямоугольника. Проблема в том, что прямоугольник всегда черный, а не зеленый! Что я тут не так делаю?

    // STAGE 1
    let fragmentShaderPass1 = `
        #extension GL_EXT_draw_buffers : require
        precision highp float;
        precision highp int;
        precision highp sampler2D;

        void main( void )
        {
            gl_FragData[0] = vec4(.2, .8, .0, 1);  // green
            gl_FragData[1] = vec4(.6, .5, .4, .3);  // brown
        }
    `;
    let pass1_prog = createProgram(gl, globals.vertexShader, fragmentShaderPass1);

    let firstStageFrameBuffer = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, firstStageFrameBuffer);

    gl.useProgram(pass1_prog);

    for (let i = 0; i < 2; i++) 
    {
        let tex = gl.createTexture();
        textures.push(tex);

        gl.bindTexture(gl.TEXTURE_2D, tex);

        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

        // attach texture to framebuffer
        gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT0_WEBGL + i, gl.TEXTURE_2D, tex, 0);
    }

    gl.disable(gl.DEPTH_TEST); // framebuffer doesn't even have a depth buffer!
    gl.viewport(0, 0, _this.canvas.width, _this.canvas.height); 

    ext.drawBuffersWEBGL([
        ext.COLOR_ATTACHMENT0_WEBGL,
        ext.COLOR_ATTACHMENT1_WEBGL
    ]);

    gl.drawArrays(gl.POINTS, 0, 1); 



    // STAGE 2
    let fragmentShaderPass2 = `
        precision highp float;
        precision highp int;
        precision highp sampler2D;

        uniform sampler2D inColor0;
        uniform sampler2D inColor1;

        void main( void )
        {
            gl_FragColor = texture2D(inColor0, vec2(0.5));
        }
    `;
    let pass2_prog = createProgram(gl, globals.vertexShader, fragmentShaderPass2);

    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

    gl.useProgram(pass2_prog);
    gl.viewport(0, 0, canvas.width, canvas.height); 
    gl.clearColor(1.0, 1.0, 1.0, 1.0);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, textures[0]);
    gl.uniform1i(gl.getUniformLocation(pass2_prog, "inColor0"), 0);

    gl.activeTexture(gl.TEXTURE1);
    gl.bindTexture(gl.TEXTURE_2D, textures[1]); 
    gl.uniform1i(gl.getUniformLocation(pass2_prog, "inColor1"), 1);

    gl.drawArrays(gl.POINTS, 0, 1);

1 Ответ

1 голос
/ 13 января 2020

Код, который вы разместили выше, не делает ваши текстуры визуализируемыми и получает эту ошибку в консоли JavaScript

ПРЕДУПРЕЖДЕНИЕ ОБ ОТКРЫТОК: текстура, привязанная к единице текстуры 0, не является визуализируемый. Это может быть не степень 2 или несовместимая фильтрация текстур (может быть)?

Они не могут быть воспроизведены, потому что у них нет mips, но они настроены на использование mips (по умолчанию). Они также, вероятно, не имеют степени 2 измерения, хотя вы не указали размер холста, а просто предположили, что это не степень 2 *.

Делаем их визуализируемыми. рендер

const canvas = document.querySelector('canvas');
const _this = {canvas};
const textures = [];
const gl = _this.canvas.getContext('webgl');
const ext = gl.getExtension('WEBGL_draw_buffers');
if (!ext) { alert('need WEBGL_draw_buffers'); }
const globals = {
  vertexShader: `
    void main() {
      gl_Position = vec4(0, 0, 0, 1);
      gl_PointSize = 100.0;
    }
  `,
}
// STAGE 1
let fragmentShaderPass1 = `
  #extension GL_EXT_draw_buffers : require
  precision highp float;
  precision highp int;
  precision highp sampler2D;

  void main( void )
  {
      gl_FragData[0] = vec4(.2, .8, .0, 1);  // green
      gl_FragData[1] = vec4(.6, .5, .4, 1);  // brown
  }
`;
let pass1_prog = createProgram(gl, globals.vertexShader, fragmentShaderPass1);

let firstStageFrameBuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, firstStageFrameBuffer);

gl.useProgram(pass1_prog);

for (let i = 0; i < 2; i++) {
  let tex = gl.createTexture();
  textures.push(tex);

  gl.bindTexture(gl.TEXTURE_2D, tex);

  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

  // attach texture to framebuffer
  gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT0_WEBGL + i, gl.TEXTURE_2D, tex, 0);
}

gl.disable(gl.DEPTH_TEST); // framebuffer doesn't even have a depth buffer!
gl.viewport(0, 0, _this.canvas.width, _this.canvas.height);

ext.drawBuffersWEBGL([
  ext.COLOR_ATTACHMENT0_WEBGL,
  ext.COLOR_ATTACHMENT1_WEBGL
]);

gl.drawArrays(gl.POINTS, 0, 1);



// STAGE 2
let fragmentShaderPass2 = `
        precision highp float;
        precision highp int;
        precision highp sampler2D;

        uniform sampler2D inColor0;
        uniform sampler2D inColor1;

        void main( void )
        {
            gl_FragColor = texture2D(inColor0, vec2(0.5));
        }
    `;
let pass2_prog = createProgram(gl, globals.vertexShader, fragmentShaderPass2);

gl.bindFramebuffer(gl.FRAMEBUFFER, null);

gl.useProgram(pass2_prog);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(1.0, 1.0, 1.0, 1.0);

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, textures[0]);
gl.uniform1i(gl.getUniformLocation(pass2_prog, "inColor0"), 0);

gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, textures[1]);
gl.uniform1i(gl.getUniformLocation(pass2_prog, "inColor1"), 1);

gl.drawArrays(gl.POINTS, 0, 1);


// ---
function createProgram(gl, vSrc, fSrc) {
  return twgl.createProgram(gl, [vSrc, fSrc]);
}
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>

Примечание. Я изменил «коричневый» цвет с vec4(.6, .5, .4, .3) на vec4(.6, .5, .4, 1). vec4(.6, .5, .4, .3) является недопустимым цветом для холста, если вы не выполняете больше математических операций на выходе или не устанавливаете холст, кроме предварительно умноженного альфа-цвета. Ваш выходной шейдер не выполнял никакой дополнительной математики, и вы не показывали свой код для настройки холста. По умолчанию браузер ожидает, что вы поместите предварительно умноженные значения цвета на холст. vec4(.6, .5, .4, .3) не является предварительно умноженным альфа, потому что если бы это было r, g и b не могли бы быть> a.

...