three.js WebGLRenderTarget
今天郭先生说一说WebGLRenderTarget,它是一个缓冲,就是在这个缓冲中,视频卡为正在后台渲染的场景绘制像素。 它用于不同的效果,例如把它做为贴图使用或者图像后期处理。线案例请点击博客原文。
话不多说,下来看看他的属性了方法。
1. WebGLRenderTarget的属性和方法
WebGLRenderTarget的构造器有三个参数,分别是width,height和options。宽高就是RenderTarget的高,设置的同时也会把它们赋值给texture.image的width和height属性。options包含以下属性
属性 | 默认值 | 描述 |
wrapS | ClampToEdgeWrapping | 包裹模式--使用RepeatWrapping,纹理将简单地重复到无穷大。使用ClampToEdgeWrapping纹理中的最后一个像素将延伸到网格的边缘。使用MirroredRepeatWrapping, 纹理将重复到无穷大,在每次重复时将进行镜像。 |
wrapT | ClampToEdgeWrapping | 同上 |
magFilter | LinearFilter | 放大滤镜--NearestFilter返回与指定纹理坐标(在曼哈顿距离之内)最接近的纹理元素的值。LinearFilter是默认值,返回距离指定的纹理坐标最近的四个纹理元素的加权平均值 |
minFilter | LinearFilter | 缩小滤镜--NearestFilter返回与指定纹理坐标(在曼哈顿距离之内)最接近的纹理元素的值。NearestMipmapNearestFilter选择与被纹理化像素的尺寸最匹配的mipmap, 并以NearestFilter(最靠近像素中心的纹理元素)为标准来生成纹理值。NearestMipmapLinearFilter选择与被纹理化像素的尺寸最接近的两个mipmap, 并以NearestFilter为标准来从每个mipmap中生成纹理值。最终的纹理值是这两个值的加权平均值。LinearFilter是默认值,返回距离指定的纹理坐标最近的四个纹理元素的加权平均值。LinearMipmapNearestFilter选择与被纹理化像素的尺寸最匹配的mipmap, 并以LinearFilter(最靠近像素中心的四个纹理元素的加权平均值)为标准来生成纹理值。LinearMipmapLinearFilter选择与被纹理化像素的尺寸最接近的两个mipmap, 并以LinearFilter为标准来从每个mipmap中生成纹理值。最终的纹理值是这两个值的加权平均值。 |
format | RGBAFormat | AlphaFormat 丢弃红、绿、蓝分量,仅读取Alpha分量。RedFormat丢弃绿色和蓝色分量,只读取红色分量RedIntegerFormat丢弃绿色和蓝色分量,只读取红色分量。texel被读取为整数而不是浮点。(只能与WebGL 2呈现上下文一起使用)。RGFormat丢弃alpha和blue组件并读取红色和绿色组件。(只能与WebGL 2呈现上下文一起使用)。RGIntegerFormat丢弃alpha和blue组件并读取红色和绿色组件。texel被读取为整数而不是浮点。(只能与WebGL 2呈现上下文一起使用)。RGBFormat 丢弃Alpha分量,仅读取红、绿、蓝分量。RGBIntegerFormat丢弃alpha组件并读取红色、绿色和蓝色组件。(只能与WebGL 2呈现上下文一起使用)。RGBAFormat将读取红、绿、蓝和Alpha分量。RGBAIntegerFormat读取红色、绿色、蓝色和alpha分量。texel被读取为整数而不是浮点。(只能与WebGL 2呈现上下文一起使用)。LuminanceFormat 将每个元素作为单独的亮度分量来读取。 将其转换为范围限制在[0,1]区间的浮点数,然后通过将亮度值放入红、绿、蓝通道,并将1.0赋给Alpha通道,来组装成一个RGBA元素。LuminanceAlphaFormat 将每个元素同时作为亮度分量和Alpha分量来读取。 和上面LuminanceFormat的处理过程是一致的,除了Alpha分量具有除了1.0以外的值。RGBEFormat 与 RGBAFormat 是相同的。DepthFormat将每个元素作为单独的深度值来读取,将其转换为范围限制在[0,1]区间的浮点数。 它是DepthTexture的默认值。DepthStencilFormat将每个元素同时作为一对深度值和模板值来读取。 其中的深度分量解释为DepthFormat。 模板分量基于深度+模板的内部格式来进行解释。 |
type | UnsignedByteType | THREE.UnsignedByteType,THREE.ByteType,THREE.ShortType,THREE.UnsignedShortType,THREE.IntType,THREE.UnsignedIntType,THREE.FloatType,THREE.HalfFloatType,THREE.UnsignedShort4444Type,THREE.UnsignedShort5551Type,THREE.UnsignedShort565Type,THREE.UnsignedInt248Type。这些常量用于纹理的type属性,这些属性必须与正确的格式相对应。详情请查看下方。 |
anisotropy | Texture.anisotropy | 沿着轴,通过具有最高纹素密度的像素的样本数。 默认情况下,这个值为1。设置一个较高的值将会产生比基本的mipmap更清晰的效果,代价是需要使用更多纹理样本。 使用renderer.getMaxAnisotropy() 来查询GPU中各向异性的最大有效值;这个值通常是2的幂。 |
encoding | LinearEncoding | THREE.LinearEncoding,THREE.sRGBEncoding,THREE.GammaEncoding,THREE.RGBEEncoding,THREE.LogLuvEncoding,THREE.RGBM7Encoding,THREE.RGBM16Encoding,THREE.RGBDEncoding,THREE.BasicDepthPacking,THREE.RGBADepthPacking。如果编码类型在纹理已被一个材质使用之后发生了改变, 你需要来设置Material.needsUpdate为true来使得材质重新编译。 |
depthBuffer | true | 深度缓冲器 |
stencilBuffer | false | 模具缓冲区 |
WebGLRenderTarget的属性
属性 | 描述 |
width | 渲染目标宽度 |
height | 渲染目标高度 |
scissor | 渲染目标视口内的一个矩形区域,区域之外的片元将会被丢弃 |
scissorTest | 表明是否激活了剪裁测试 |
viewport | 渲染目标的视口 |
texture | 纹理实例保存这渲染的像素,用作进一步处理的输入值 |
depthBuffer | 渲染到深度缓冲区。默认true |
stencilBuffer | 渲染到模具缓冲区。默认false |
depthTexture | 如果设置,那么场景的深度将会被渲染到此纹理上。默认是null |
WebGLRenderTarget的方法
方法 | 描述 |
setSize | 设置渲染目标的大小 |
clone | 创建一个渲染目标副本 |
copy | 采用传入的渲染目标的设置 |
dispose | 发出一个处理事件 |
2 使用WebGLRenderTarget作为贴图案例
1 做一个网格
首先做一个几何体,这里我们以THREE.Line为例
let pointArr = []; let colorArr = []; const points = GeometryUtils.hilbert2D(new THREE.Vector3( 0, 0, 0 ), 10, 3); for(let i=0; i<points.length; i++) { pointArr.push(points[i].x, points[i].y, points[i].z); colorArr.push(Math.random(), Math.random(), Math.random()); } const geometry = new THREE.BufferGeometry(); const positionAttribute = new THREE.Float32BufferAttribute( pointArr, 3 ); geometry.setAttribute( 'position', positionAttribute ); geometry.center(); const colorAttribute = new THREE.BufferAttribute( new Float32Array( colorArr ), 3 ); colorAttribute.setUsage( THREE.DynamicDrawUsage ); geometry.setAttribute( 'color', colorAttribute ); const material = new THREE.LineBasicMaterial( { vertexColors: true } ); line = new THREE.Line( geometry, material ); sceneRTT.add( line );
这就做好了一个line,这里说一下scene是我们的主场景,camera是拍摄主场景的相机,sceneRTT是renderTarget的场景,cameraRTT是rennderTarget的相机。GeometryUtils.hilbert2D是生成希尔伯特曲线的方法。
2. 创建render target
我们创建一个render target,里面的参数不清楚的可以多次尝试一下
target = new THREE.WebGLRenderTarget(200, 200, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat }); target.viewport = new THREE.Vector4(10,10,180,180);
这里我们设置视口起点从(10, 10)开始,宽高分别为180的矩形。
3. 创建渲染器和要贴图的Mesh
接下来我们创建渲染器和要贴图的Mesh
renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setSize(window.innerWidth, window.innerHeight); this.$refs.box.appendChild(renderer.domElement); let boxGeom = new THREE.BoxBufferGeometry(100, 100, 100); let boxMate = new THREE.MeshBasicMaterial({map: target.texture}); let boxMesh = new THREE.Mesh(boxGeom, boxMate); scene.add(boxMesh)
直接调用target的Texture属性来做材质的贴图
4. 渲染
这里要渲染render target的场景,这样调用target.texture才能返回一个正经的贴图,同时我们让这个贴图随时间变换,最后渲染主场景,代码如下。
onst colorAttribute = line.geometry.getAttribute( 'color' ); const l = colorAttribute.count; for(let i=0; i<l; i++) { const h = ( ( offset + i ) % l ) / l * 20; color.setHSL(h, 0.8, 0.5); colorAttribute.setX( i, color.r ); colorAttribute.setY( i, color.g ); colorAttribute.setZ( i, color.b ); } colorAttribute.needsUpdate = true; offset -= 0.2; renderer.setRenderTarget( target ); renderer.setClearColor(0xffddff); renderer.clear(); renderer.render( sceneTT, cameraTT ); renderer.setRenderTarget( null ); renderer.setClearColor(0x000000); renderer.render( scene, camera ); this.globalID = requestAnimationFrame(this.render);
这样就可以把render target作为贴图使用了。
转载请注明地址:郭先生的博客