热浪扭曲效果

 
热浪扭曲
          每个人都对自然界中的这种大气效果很熟悉
          光线在穿过不同密度的介质时会弯曲
 
热微光
          热空气密度比冷空气小
          密度影响介质的折射率
          热空气上升的同时会被冷空气替代, 这会改变光射入眼睛的路线
 
          渲染场景到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);
}
 

### Unity 中实现热浪效果的方法 在 Unity 中实现热浪效果主要依赖于 **屏幕后处理技术** 和 **Shader 编写能力**。以下是关于如何实现这一效果的具体方法: #### 使用 Shader 实现热浪扭曲效果 热浪效果的核心在于模拟空气因温度差异引起的光线折射现象。这可以通过编写自定义的 Shader 来完成,具体思路如下: - 利用噪声纹理(Noise Texture)作为输入数据源来控制像素偏移量。 - 在顶点着色器或片段着色器中应用基于时间变化的扰函数。 下面是一个简单的 Heat Distortion Shader 的代码示例[^2]: ```hlsl // HotAirDistortion.shader Shader "Custom/HotAirDistortion" { Properties { _MainTex ("Texture", 2D) = "white" {} _NoiseTex ("Noise Texture", 2D) = "gray" {} _Strength ("Distortion Strength", Float) = 0.1 _Speed ("Animation Speed", Float) = 1.0 } SubShader { Tags { "Queue"="Transparent" "RenderType"="Opaque" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex, _NoiseTex; float _Strength, _Speed; v2f vert (appdata_t v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { // Sample noise texture with time-based offset. float2 distortionUV = i.uv + (_Time.y * _Speed); float2 distortionOffset = tex2D(_NoiseTex, distortionUV).rg * _Strength; // Apply the distortion to main texture sampling coordinates. float2 finalUV = i.uv + distortionOffset; fixed4 col = tex2D(_MainTex, finalUV); return col; } ENDCG } } } ``` 此 Shader 需要配合一个带有 `OnRenderImage` 函数的 C# 脚本来执行全屏绘制操作: ```csharp using UnityEngine; public class HeatWaveEffect : MonoBehaviour { public Material heatWaveMaterial; private void OnRenderImage(RenderTexture source, RenderTexture destination) { Graphics.Blit(source, destination, heatWaveMaterial); } } ``` 上述脚本会将场景最终渲染结果传递给指定材质进行后期处理[^2]。 #### 设置天空盒增强视觉氛围 为了使热浪效果更加逼真,在调整环境光的同时也可以考虑更换适合高温天气条件下的 Skybox 。按照以下步骤更改当前项目的默认天空资源即可影响到 Game View 及 Scene View 显示样式[^1]: 1. 打开 Window -> Rendering -> Lighting Settings 对话框; 2. 寻找 Environment 下拉菜单中的 Skybox Material 参数项; 3. 替换为预设好的夏日晴朗型素材或者自制渐变色彩方案; 另外还可以引入第三方资产包如 HDRI Haven 提供高质量全景像进一步提升画质表现力。 #### 层级优化减少性能消耗 当项目规模较大时应关注不必要的远处物体渲染带来的负担问题。借助 Camera 组件属性 Layer Culling Distance 功能能够有效缓解此类状况发生几率。例如针对某些特定层标签的小尺寸模型提前设定好最大可见范围从而避免超出合理界限后的无谓计算过程[^4]: ```csharp void ConfigureLayerCulling() { Camera cam = GetComponent<Camera>(); if(cam != null){ float[] cullDistances = new float[32]; cullDistances[(int)Layers.NameToLayer("SmallProps")] = 50f; cam.layerCullDistances = cullDistances; } } ``` 以上代码展示了怎样限定名为 SmallProps 这一层里的所有成员只会在距相机中心半径不超过五十单位以内才被纳入绘队列之中去。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值