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