是否可以使用绑定到本机帧缓冲区的gl.Texture_2D更新THREE.Texture?

时间:2016-02-13 11:15:13

标签: three.js framebuffer

这个想法: 使用本机WebGL帧缓冲创建一个renderTexture,以便能够使用" WEBGL_draw_buffers"并输出多个附件(COLOR_ATTACHMENT0_WEBGL,COLOR_ATTACHMENT1_WEBGL,COLOR_ATTACHMENT2_WEBGL,...)

glFragData[0] = ...
glFragData[1] = ...
glFragData[2] = ...
glFragData[3] = ...

然后,尝试使用绑定到帧缓冲区的这些附加的本机WebGL texture2D更新一些THREE.DataTextures。

使用WEBGL_draw_buffers扩展程序,我的本机帧缓冲区一切正常......但我找不到更新threejs纹理的方法。我通过查看Threejs如何处理WebGLRenderTarget尝试了很多东西......但没有任何工作......没有办法用原生WebGL Texture2D更新THREE.Texture。

我不想使用WebGLRenderTarget,因为只有一个COLOR_ATTACHMENT并且它不支持" WEBGL_draw_buffers"延期。 也许将来处理这个会很好;)

知道如何实现这个目标吗?

这就是我在代码方面的意思:

var scene;
var camera;
var renderer;
var debugMaterial;
var posTextureOut;

function init()
{
    // create a data texture + generate a gl.Texture2D for it

    posTextureOut = new THREE.DataTexture(posTextureData, rttSize, rttSize, THREE.RGBAFormat, THREE.FloatType);
    posTextureOut.__webglTexture = gl.createTexture();
    posTextureOut.__webglInit = true;
    posTextureOut.needsUpdate = true;

    // create a framebuffer and bind posTextureOut.__webglTexture to it

    rttFramebuffer = gl.createFramebuffer();
    renderFrameBuffer = gl.createRenderbuffer();

        gl.bindTexture(gl.TEXTURE_2D, posTextureOut.__webglTexture);
        //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, rttSize, rttSize, 0, gl.RGBA, gl.FLOAT, null);
        gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);
        gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT0_WEBGL, gl.TEXTURE_2D, posTextureOut.__webglTexture, 0);
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
        gl.bindTexture(gl.TEXTURE_2D, null);


        // Bind RenderBuffer to FrameBuffer Depth and Stencil attachment

        gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);
        gl.bindRenderbuffer(gl.RENDERBUFFER, renderFrameBuffer);
        gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, rttSize, rttSize );
        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderFrameBuffer );
        gl.bindRenderbuffer(gl.RENDERBUFFER, null);
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);



    // create material with classic vert/frag shaders + posTextureOut as mainTexture

    debugMaterial = new THREE.ShaderMaterial({
        uniforms:
        {
            texture: { type: "t", value: posTextureOut }
        },
        vertexShader: shaderLoader.GetData("simulVert"),
        fragmentShader:  shaderLoader.GetData("simulFrag"),  
        transparent: true,
        needsUpdate: true
   });

   var geometry = new THREE.PlaneGeometry( 128, 128, 8, 8 );
   plane = new THREE.Mesh( geometry, debugMaterial );

   scene.add( plane );
}

function render()
{
   gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);

   // Draw some stuff width gl.drawArrays or gl.drawElements

   gl.bindFramebuffer(gl.FRAMEBUFFER, null);


   // ... find a way to update posTextureOut width the native texture2D from the framebuffer


   renderer.resetGLState();  // errors in renderer if this is not called (??)

   renderer.render(scene, camera);
}

如果我这样做,我会让它部分工作:

function render()
{
   gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);

   // Draw some stuff width gl.drawArrays or gl.drawElements

   gl.bindFramebuffer(gl.FRAMEBUFFER, null);


   renderer.resetGLState(); 


   gl.bindTexture(gl.TEXTURE_2D, posTextureOut.__webglTexture);

   renderer.render(scene, camera);

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

但它并不真正适合ThreeJS渲染器管道,我无法控制使用哪个activeTexture,无论gl.activeTexture(gl.TEXTURE0)gl.TEXTURE1,gl.TEXTURE2是否在之前传递结合。

我真的想从我的网格材质中使用自定义帧缓冲区的内容更新我的posTextureOut(THREE.DataTexture)。

听起来像THREE.Textures没有考虑对其__webglTexture的任何更改。

由于

Q值。

1 个答案:

答案 0 :(得分:1)

好的,我想我找到了为什么我无法使用texture2D参考更新THREE.Texture。

要使用gl.createTexture()设置THREE.Texture,我通过谷歌搜索找到了这个:

posTextureOut = new THREE.DataTexture(posTextureData, rttSize, rttSize, THREE.RGBAFormat, THREE.FloatType);
posTextureOut.__webglTexture = gl.createTexture();
posTextureOut.__webglInit = true;
posTextureOut.needsUpdate = true;

然后,如果你想将这个纹理绑定到一个原生的framebuffer并在其上做一些原生的webgl东西,你可以这样做:

gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);
...
ext.drawBuffersWEBGL([ext.COLOR_ATTACHMENT0_WEBGL, ext.COLOR_ATTACHMENT1_WEBGL]);

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, posTextureOut.__webglTexture);
...
...
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);

gl.bindFramebuffer(gl.FRAMEBUFFER, null);

使用此修改过的posTextureOut .__ webglTexture更新了THREE.Texture的问题

使用needsUpdate = true对我没有帮助,并且由于纹理绑定到THREE.WebGLRenderer而导致很多错误。

通过查看源代码,我发现了问题。 在THREE.WebGLRenderer中,this.setTexture方法如下所示:

this.setTexture = function ( texture, slot ) {

    var textureProperties = properties.get( texture );

    if ( texture.version > 0 && textureProperties.__version !== texture.version ) {

        var image = texture.image;

        if ( image === undefined ) {

            console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture );
            return;

        }

        if ( image.complete === false ) {

            console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture );
            return;

        }

        uploadTexture( textureProperties, texture, slot );

        return;
    }

    state.activeTexture( _gl.TEXTURE0 + slot );
    state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );

};

this.uploadTexture方法正在执行此操作:

function uploadTexture( textureProperties, texture, slot ) {

    if ( textureProperties.__webglInit === undefined ) {

        textureProperties.__webglInit = true;

        texture.addEventListener( 'dispose', onTextureDispose );

        textureProperties.__webglTexture = _gl.createTexture();

        _infoMemory.textures ++;

    }

此时,textureProperties .__ webglInit始终未定义,即使它之前被强制。相同的前面textureProperties .__ webglTexture ...总是未定义。

我通过强制this.setTexture来修复此问题,以查看纹理并查看此比例是否有任何更改...否则,渲染器不会考虑它。

以下是我添加的两行:

this.setTexture = function ( texture, slot ) {

    var textureProperties = properties.get( texture );

    if (texture.__webglInit != undefined) textureProperties.__webglInit = texture.__webglInit;
    if (texture.__webglTexture != undefined) textureProperties.__webglTexture = texture.__webglTexture;

    if ( texture.version > 0 && textureProperties.__version !== texture.version ) {

        var image = texture.image;

        ....

现在一切正常......我可以在原生WebGL中处理THREE.Texture __webglTexture:)