Shader Materials and GL Framebuffers in THREE.js
Asked Answered
J

2

1

I'm trying to use an FBO in a material in THREE.js. I have a GPU-based fluid simulation which outputs its final visualisation to a framebuffer object, which I would like to use to texture a mesh. Here's my simple fragment shader:

varying vec2 vUv;
uniform sampler2D tDiffuse;

void main() {

    gl_FragColor = texture2D( tDiffuse, vUv );

}

I am then trying to use a simple THREE.ShaderMaterial:

var material = new THREE.ShaderMaterial( {

    uniforms: { tDiffuse: { type: "t", value: outputFBO } },
    //other stuff... which shaders to use etc
} );

But my mesh just appears black, albeit with no errors to the console. If I use the same shader and shader material, but supply the result of THREE.ImageUtils.loadTexture("someImageOrOther") as the uniform to the shader, it renders correctly, so I assume the problem is with my FBO. Is there some convenient way of converting from an FBO to a Texture2D in WebGL?

EDIT:

After some more experimentation it would appear that this isn't the problem. If I pass the FBO to a different shader I wrote that just outputs the texture to the screen then it displays fine. Could my material appear black because of something like lighting/normals?

EDIT 2:

The UVs and normals are coming straight from THREE, so I don't think it can be that. Part of the problem is that most shader errors aren't reported so I have difficulty in that regard. If I could just map the WebGLTexture somehow that would make everything easier, perhaps like this

var newMaterial = new THREE.MeshLambertMaterial({ map : outputFBO.texture });

but of course that doesn't work. I haven't been able to find any documentation that suggests THREE can read directly from WebGLTextures.

Jumpy answered 26/3, 2013 at 16:9 Comment(5)
It's called "render to texture". mrdoob.github.com/three.js/examples/webgl_rtt.htmlFerretti
Sorry, I think you have misunderstood me. I am already drawing to a texture (actually an FBO containing a texture). I do not have a problem with that. What I am trying to do now is to use this WebGLTexture to texture a mesh in THREE.jsJumpy
The example I referenced is doing exactly that. It is rendering to a WebGLRenderTarget and using the WebGLRenderTarget as a texture for the material for a mesh.Ferretti
That is not the same thing. That example demonstrates THREE's renderer drawing to a THREE.WebGLRenderTarget. I have a separate system for drawing to a GL data structure (eg WebGLTexture or WebGLFramebuffer, as documented in the full WebGL spec [khronos.org/registry/webgl/specs/latest/]) - if I could use THREE's data structures (as in that example) then I would.Jumpy
Yes, I was suggesting you use three.js data structures. I understand now that using your data structure is a hard constraint.Ferretti
O
0

By poking a little into the sources of WebGLRenderer (look at https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L6643 and after), you may try to create a three js texture with a dummy picture, then change the data member __webglTexture of this texture by putting your own webgltexture.

Also, you may need to set to true the __webglInit data member of the texture object so that init code is not executed (because then __webglTexture is overwritten by a call to _gl.createTexture();)

Orangery answered 27/3, 2013 at 17:28 Comment(0)
A
0

If you don't mind using the Three.js data structures, here's how you do it:

Three.js use framebuffer as texture

Athey answered 8/2, 2014 at 20:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.