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作爲貼圖使用了。

 

轉載請註明地址:郭先生的博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章