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作为贴图使用了。

 

转载请注明地址:郭先生的博客

posted @ 2020-12-28 16:17  郭先生的博客  阅读(3691)  评论(0编辑  收藏  举报