Three.js使用framebuffer作为纹理

mee*_*tar 13 fragment-shader three.js

我使用canvas元素中的图像作为Three.js中的纹理,使用JavaScript在画布上执行图像处理,然后在纹理上调用needsUpdate().这有效,但速度很慢.

我想在片段着色器中执行图像计算.我发现很多例子几乎都是这样的:

  • 着色器材质:http://mrdoob.github.io/three.js/examples/webgl_shader2.html此示例显示在片段着色器中执行的图像处理,但该着色器用作整个材质的片段着色器.我只想在纹理上使用着色器,然后将纹理用作第二种材质的组件.

  • 渲染到纹理:https://threejsdoc.appspot.com/doc/three.js/examples/webgl_rtt.html这显示将整个场景渲染到WebGLRenderTarget并将其用作材质中的纹理.我只想预处理图像,而不是渲染整个场景.

  • 效果作曲家:http://www.airtightinteractive.com/demos/js/shaders/preview/这表示将着色器应用为整个场景的后期处理.

编辑:这是另一个:

据我所知,理想情况下,我可以使用自己的片段着色器创建一个新的帧缓冲对象,自己渲染它,并将其输出用作另一个材质片段着色器的纹理均匀.这可能吗?

编辑2:看起来我可能会问这样的事情:THREE.js中的Shader Materials和GL Framebuffers ......虽然这个问题似乎没有得到解决.

mee*_*tar 24

渲染到纹理渲染到上面列出的另一个场景是相同的,并且是您想要的技术.解释:

在vanilla WebGL中,你做这种事情的方法是从头开始创建一个帧缓冲对象(FBO),将纹理绑定到它,然后使用你选择的着色器渲染它.不涉及"场景"和"相机"等概念,这是一个复杂的过程.这是一个例子:

http://learningwebgl.com/blog/?p=1786

但这也恰好是Three.js在使用它来渲染带摄像头的场景时所做的事情:渲染器输出到帧缓冲区,帧缓冲区在其基本用法中直接进入屏幕.因此,如果您指示它渲染到新的WebGLRenderTarget,您可以使用相机看到的任何内容作为第二种材质的输入纹理.所有复杂的东西仍在发生,但在幕后,这是Three.js的美丽.:)

因此:要复制包含单个渲染纹理的FBO的WebGL设置(如注释中所述),只需使用所需纹理创建包含正交相机和单个平面的新场景,然后使用所需纹理渲染到新的WebGLRenderTarget您的自定义着色器:

// new render-to-texture scene
myScene = new THREE.Scene();

// you may need to modify these parameters
var renderTargetParams = {
  minFilter:THREE.LinearFilter,
  stencilBuffer:false,
  depthBuffer:false
};

myImage = THREE.ImageUtils.loadTexture( 'path/to/texture.png',
  new THREE.UVMapping(), function() { myCallbackFunction(); } );

imageWidth = myImage.image.width;
imageHeight = myImage.image.height;

// create buffer
myTexture = new THREE.WebGLRenderTarget( width, height, renderTargetParams );

// custom RTT materials
myUniforms = {
  colorMap: { type: "t", value: myImage },
};
myTextureMat = new THREE.ShaderMaterial({
  uniforms: myUniforms,
  vertexShader: document.getElementById( 'my_custom_vs' ).textContent,
  fragmentShader: document.getElementById( 'my_custom_fs' ).textContent
});

// Setup render-to-texture scene
myCamera = new THREE.OrthographicCamera( imageWidth / - 2,
  imageWidth / 2,
  imageHeight / 2,
  imageHeight / - 2, -10000, 10000 );

var myTextureGeo = new THREE.PlaneGeometry( imageWidth, imageHeight );
myTextureMesh = new THREE.Mesh( myTextureGeo, myTextureMat );
myTextureMesh.position.z = -100;
myScene.add( myTextureMesh );

renderer.render( myScene, myCamera, myTexture, true );
Run Code Online (Sandbox Code Playgroud)

渲染完新场景后,myTexture将可用作主场景中另一种材质的纹理.请注意,您可能希望renderloadTexture()调用中使用回调函数触发第一个,以便在源图像加载之前不会尝试渲染.

  • 没有冒犯,真的; 谢谢你的帮助.我不知道那些线是什么.它们是遗传的,继承自祖先,在编程和进化中一样,代码不会明显抑制生存能力.但是我会编辑这个例子以减少对后代的混淆. (3认同)
  • 正交相机的近平面真的不应该在相机后面; 它应该是一个积极的价值.什么是`THREE.RenderTargetWrapping`?你在这种情况下使用`type = THREE.FloatType`的原因是什么? (2认同)