今天郭先生說一說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作為貼圖使用了。
轉載請注明位址:郭先生的部落格