three.js WebGLRenderTarget

郭先生的部落格發表於2020-12-28

今天郭先生說一說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作為貼圖使用了。

 

轉載請註明地址:郭先生的部落格

相關文章