2015-08-20 7 views
1

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

Сначала я инициализацию, контекст:

 gl = canvas.getContext("webgl",{stencil:true}); 

затем

function initFBO() 
{ 

for (var i = 0; i < shaderPrograms.length; i++) 
{ 

    var texture = createTexture(imgWidth,imgHeight); 
    textures.push(texture); 

    var fbo = gl.createFramebuffer(); 
    framebuffers.push(fbo); 

    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 

    var renderbuffer = gl.createRenderbuffer(); 

    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer); 
    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, imgWidth, imgHeight); 
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); 
    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer); 

} 
} 


function drawScene() 
{ 
gl.enable(gl.STENCIL_TEST); 
gl.enable(gl.DEPTH_TEST); 

if(!useFBO) 
{ 
    computeProgFBO(9,null,imgHeight,imgHeight,textureId,null,null,false); 
    computeProgFBO(8,null,imgHeight,imgHeight,textureId,null,null,false); 
}else{ 
    computeProgFBO(9,framebuffers[0],imgHeight,imgHeight,textureId,null,null,false); 
    computeProgFBO(8,null,imgHeight,imgHeight,textures[0],null,null,false); 
} 

// Restore the original matrix 
mvPopMatrix(); 

gl.disable(gl.STENCIL_TEST); 
gl.disable(gl.DEPTH_TEST); 

} 

function computeProgFBO(progId,fboId,w,h,textureId0,textureId1,textureId2,flip) 
{ 

    currentProgram=shaderPrograms[progId]; 
    gl.useProgram(currentProgram); 

    if(progId==9) 
    { 
     transform(w,h,0.0); 
     gl.stencilMask(1); 
     gl.stencilFunc(gl.ALWAYS,1,0); 
     gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); 
     gl.colorMask(true, true, true, true); 
     gl.depthMask(false); 
     setMatrixUniformsView(); 
    }else{ 
     gl.colorMask(true, true, true, true); 
     gl.depthMask(true); 
     gl.stencilFunc(gl.EQUAL,0,1); 
     gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); 
     setMatrixUniforms(); 
    } 

    setMyUniforms(progId,flip); 
    setMyTexture(textureId0, textureId1,textureId2); 

    gl.activeTexture(gl.TEXTURE1); 
    gl.bindFramebuffer(gl.FRAMEBUFFER, fboId); 
//the below is commented out for now as i'm only testing the stencil buffer for now   
// gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[progId], 0); 




    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); 

    gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
    gl.bindTexture(gl.TEXTURE_2D , null); 
} 

Я не думаю, что есть любая точка, показывающая различные формы и функции текстуры, но, пожалуйста, дайте мне знать, в противном случае. Кстати, прогейм 9 рисует маленький зеленый квадрат и прогоняет 8 большой красный квадрат поверх него. Итак, я ожидаю увидеть зеленый квадрат, окруженный красными краями, как это показано на экране, когда я выхожу прямо на экран.

**** ДАЛЕЕ на 1-й ответ я поправку ниже *****

if(!useFBO) 
{ 
    computeProgFBO(9,null,imgHeight,imgHeight,textureId,null,null,false,null); 
    computeProgFBO(8,null,imgHeight,imgHeight,textureId,null,null,false,null); 
    computeProgFBO(6,null,imgHeight,imgHeight,textureId,null,null,false,null); 
}else{ 
    computeProgFBO(9,framebuffers[0],imgHeight,imgHeight,textureId,null,null,false,null); 
    computeProgFBO(8,framebuffers[1],imgHeight,imgHeight,textures[0],null,null,false,renderbuffers[0]); 
    computeProgFBO(6,null,imgHeight,imgHeight,textures[1],null,null,false,null); 
} 

и я изменил аргументы функции в

computeProgFBO(progId,fboId,w,h,textureId0,textureId1,textureId2,flip,render) 

и там после того, как ниже комментарий

//the below is commented out for now as i'm only testing the stencil buffer for now   
// gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[progId], 0); 

я добавил

if(render!=null) 
    { 
     gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, render); 
    } 

Результат немного лучше, но не совсем то, что я ожидал, то есть: im получая большой красный квадрат, а вместо того, чтобы иметь маленький зеленый квадрат внутри, я получаю белый квадрат. Я чувствую, что это что-то тривиальное, но пока не может его обработать. Рендеринг прямо на экран по-прежнему отлично работает.

***** ДАЛЕЕ комментарии от других я добавил ******

я думаю, я понимаю проблему и нашел обходной путь для него [не очень элегантно Тхо]. В основном, первый проход записывает с использованием трафарета в текстуры [0] фреймбуферов [0], а 2-й проход записывает в текстуры [1] фреймбуферов [1] с помощью рендеринга буферов [0] фреймбуферов [0], но не текстур [0 ]. Следовательно, я получаю только небольшой белый [вместо зеленого] квадрат, окруженный красным. Так, я не могу Blit, я понял, что я могу просто сделать два раза в первом проходе согласно ниже:

.... 
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); 

if(progId==9) 
    { 
     gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffers[1]); 
     gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); 
    } 

Это работает, но выглядит очень некрасиво! Есть ли другой путь?

Когда дело доходит до рендеринга финальной текстуры на экране, мне кажется, что мне не нужно много делать, т. Е. Я посылаю только цветной буфер на экран (а не трафаретный буфер &) и все окончательные текстура отображается, как ожидалось.

Кроме того, обратите внимание, что мой фрагмент шейдеры только делает ниже

shader9: gl_FragColor = vec4(0.0,1.0,0.0,1.0);

shader8: gl_FragColor = vec4(1.0,vec2(0.0),1.0);

shader6: gl_FragColor = texture2D(u_Texture0,vTextureCoord);

+0

WebGL - ваше самое большое препятствие ... у вас есть расширение ['GL_ANGLE_framebuffer_blit'] (https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_blit.txt)? –

+0

Можете прояснить, что здесь препятствие? это потому, что im использует чтение и запись фреймбуферов, и по некоторым причинам копия с одного на следующий не работает? (или я должен сказать, что работа для текстуры, но не для глубины и трафарета?) – RogerLePatissier

+0

Копирование буфера трафарета невозможно без 'glBlitFramebuffer (...)'. У вас нет поддержки текстур трафарета в WebGL и нет механизма для копирования рендеринга. –

ответ

2

Вы не можете копировать содержимое буферов webgl, но вы можете совместно использовать буфер глубины-трафарета между многими FBOS, вызывая gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer); на том же рендеринге.

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

+0

спасибо за отзыв. Я изменил код в соответствии с рекомендацией (см. Поправку на вопрос), но теперь вместо того, чтобы иметь зеленый квадрат, окруженный красной рамкой, у меня есть только красная рамка, а зеленый квадрат белый? – RogerLePatissier

+0

У меня нет времени, чтобы просмотреть свой код. Вы сделали вторую часть, которую я предложил? То есть вы должны сначала перенести на другой FBO (до передачи FBO по умолчанию) с общим буфером трафарета, а затем нарисовать содержимое этого FBO в FBO по умолчанию. –