熱浪扭曲 • 每個人都對自然界中的這種大氣效果很熟悉 • 光線在穿過不同密度的媒體時會彎曲 熱微光
• 熱空氣密度比冷空氣小 • 密度影響媒體的折射率 • 熱空氣上升的同時會被冷空氣替代, 這會改變光射入眼睛的路線 • 渲染場景到RGBA離屏緩存(可渲染的紋理) • 顔色寫入RGB值 • 扭曲度寫入Alpha通道 • 繪制全屏長方形到後備緩沖區 • 對離屏緩沖采樣以獲得扭曲度 • 用擾動貼圖來确定擾動向量, 用扭曲度放縮後偏移原始紋理坐标 • 基于擾動紋理坐标的可增長 泊松分布(根據扭曲度來進行偏移) 扭曲度 • 逐像素判斷目前像素被扭曲的程度 • 當光線穿過更多的氣體時, 折射程度也相應增加 • 扭曲随場景深度增加 – 開始時把渲染目标的Alpha通道清為1.0,表示最大深度 – Pixel shader把每個像素的深度寫入alpha通道 • 深度提供了一個很好的全局扭曲方案, 但是你的美工們希望局部控制 • 熱浪幾何體可以用來定義扭曲範圍, 如熱空氣出口和噴氣發動機尾 • 熱浪紋理可以使熱浪幾何本上的扭曲動起來 熱度幾何體 & 熱度紋理
• 像素扭曲度來源來熱度紋理 • 扭曲度被深度放大 • 用高度進一步放大 (紋理坐标) 并且 N.V 來避免生硬的邊緣 • 扭曲度被寫入Alpha通道 全屏矩形 • 全屏矩形用離屏緩存(可渲染的紋理)來繪制并且用擾動貼圖作為紋理 擾動貼圖
• 一個2D向量儲存在紅色和綠色通道内 • 在全屏矩形兩個方向上卷動貼圖并采樣兩次 • 平均兩次采樣并把值變換到 [-1.0, 1.0] 的範圍内 • 用扭曲度放縮向量 • 結果就是扭曲向量 扭曲向量
• 扭曲向量用于偏移原始紋理坐标 • 向量的大小取決于扭曲度 • 這個新的擾動紋理用于讀入離屏緩存 可增長泊松分布
• 模糊中心在擾動紋理坐标的中間 • 偏移基于扭曲度 扭曲 Shader
float4 main ( PsInput i) : COLOR { // fetch from perturbation map with scrolling texture coords float3 vPerturb0 = tex2D (tPerturbationMap, i.texCoord1); float3 vPerturb1 = tex2D (tPerturbationMap, i.texCoord2); // scale and bias: (color - 0.5f)*2.0f vPerturb0 = SiConvertColorToVector(vPerturb0); vPerturb1 = SiConvertColorToVector(vPerturb1); // average perturbation vectors float2 offset = (vPerturb0.xy + vPerturb1.xy) * 0.5f; // get distortion weight from renderable texture (stored in alpha) float4 cDistWeight = tex2D (tRBFullRes, i.texCoord0); // square distortion weight cDistWeight.a *= cDistWeight.a; // compute distorted texture coords offset.xy = ((offset.xy * cDistWeight.a) * fPerturbScale) + i.texCoord0; // fetch the distorted color float4 o; o.rgb = SiPoissonDisc13RGB(tRBFullRes, offset, 1.0f/screenRes.xy, cDistWeight.a); o.a = 1.0f; return o; } |
可增長泊松分布 Shader
float3 SiGrowablePoissonDisc13FilterRGB ( sampler tSource, float2 texCoord, float2 pixelSize, float discRadius) { float3 cOut; float2 poisson[12] = { float2 (-0.326212f, -0.40581f), float2 (-0.840144f, -0.07358f), float2 (-0.695914f, 0.457137f), float2 (-0.203345f, 0.620716f), float2 (0.96234f, -0.194983f), float2 (0.473434f, -0.480026f), float2 (0.519456f, 0.767022f), float2 (0.185461f, -0.893124f), float2 (0.507431f, 0.064425f), float2 (0.89642f, 0.412458f), float2 (-0.32194f, -0.932615f), float2 (-0.791559f, -0.59771f)}; // Center tap cOut = tex2D (tSource, texCoord); for ( int tap = 0; tap < 12; tap++) { float2 coord = texCoord.xy + (pixelSize * poisson[tap] * discRadius); // Sample pixel cOut += tex2D (tSource, coord); } return (cOut / 13.0f); } |