原理:
和之前的差不多,只是添加了噪声相关的参数和属性,并在Shader的片元着色器中对高度的计算添加了噪声的影响
脚本实现
using UnityEngine;
using System. Collections; public class FogWithNoise : PostEffectsBase
{ public Shader fogShader; private Material fogMaterial = null ; public Material material{ get { fogMaterial = CheckShaderAndCreateMaterial ( fogShader, fogMaterial) ; return fogMaterial; } } private Camera myCamera; public Camera Camera{ get { if ( myCamera == null ) { myCamera = GetComponent < Camera > ( ) ; } return myCamera; } } private Transform myCameraTransform; public Transform cameraTransform{ get { if ( myCameraTransform == null ) { myCameraTransform = Camera. transform; } return myCameraTransform; } } [ Range ( 0.1f , 3.0f ) ] public float fogDensity = 1.0f ; public Color fogColor = Color. white; public float fogStart = 0.0f ; public float fogEnd = 2.0f ; public Texture noiseTexture; [ Range ( - 0.5f , 0.5f ) ] public float fogXSpeed = 0.1f ; [ Range ( - 0.5f , 0.5f ) ] public float fogYSpeed = 0.1f ; [ Range ( 0.0f , 3.0f ) ] public float noiseAmount = 1.0f ; void OnEnable ( ) { GetComponent < Camera > ( ) . depthTextureMode | = DepthTextureMode. Depth; } void OnRenderImage ( RenderTexture src, RenderTexture dest) { if ( material != null ) { Matrix4x4 frustumCorners = Matrix4x4. identity; float fov = Camera. fieldOfView; float near = Camera. nearClipPlane; float aspect = Camera. aspect; float halfHeight = near * Mathf. Tan ( fov * 0.5f * Mathf. Deg2Rad) ; Vector3 toRight = cameraTransform. right * halfHeight * aspect; Vector3 toTop = cameraTransform. up * halfHeight; Vector3 topLeft = cameraTransform. forward * near + toTop - toRight; float scale = topLeft. magnitude / near; topLeft. Normalize ( ) ; topLeft * = scale; Vector3 topRight = cameraTransform. forward * near + toRight + toTop; topRight. Normalize ( ) ; topRight * = scale; Vector3 bottomLeft = cameraTransform. forward * near - toTop - toRight; bottomLeft. Normalize ( ) ; bottomLeft * = scale; Vector3 bottomRight = cameraTransform. forward * near + toRight - toTop; bottomRight. Normalize ( ) ; bottomRight * = scale; frustumCorners. SetRow ( 0 , bottomLeft) ; frustumCorners. SetRow ( 1 , bottomRight) ; frustumCorners. SetRow ( 2 , topRight) ; frustumCorners. SetRow ( 3 , topLeft) ; material. SetMatrix ( "_FrustumCornersRay" , frustumCorners) ; material. SetFloat ( "_FogDensity" , fogDensity) ; material. SetColor ( "_FogColor" , fogColor) ; material. SetFloat ( "_FogStart" , fogStart) ; material. SetFloat ( "_FogEnd" , fogEnd) ; material. SetTexture ( "_NoiseTex" , noiseTexture) ; material. SetFloat ( "_FogXSpeed" , fogXSpeed) ; material. SetFloat ( "_FogYSpeed" , fogYSpeed) ; material. SetFloat ( "_NoiseAmount" , noiseAmount) ; Graphics. Blit ( src, dest, material) ; } else { Graphics. Blit ( src, dest) ; } }
}
Shader实现
Shader "Fog With Noise"
{ Properties { _MainTex ( "Base (RGB)" , 2 D) = "white" { } _FogDensity ( "Fog Density" , Float) = 1.0 _FogColor ( "Fog Color" , Color) = ( 1 , 1 , 1 , 1 ) _FogStart ( "Fog Start" , Float) = 0.0 _FogEnd ( "Fog End" , Float) = 1.0 _NoiseTex ( "Noise Texture" , 2 D) = "white" { } _FogXSpeed ( "Fog Horizontal Speed" , Float) = 0.1 _FogYSpeed ( "Fog Vertical Speed" , Float) = 0.1 _NoiseAmount ( "Noise Amount" , Float) = 1 } SubShader { CGINCLUDE#include "UnityCG.cginc" float4x4 _FrustumCornersRay; sampler2D _MainTex; half4 _MainTex_TexelSize; sampler2D _CameraDepthTexture; half _FogDensity; fixed4 _FogColor; float _FogStart; float _FogEnd; sampler2D _NoiseTex; half _FogXSpeed; half _FogYSpeed; half _NoiseAmount; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; float2 uv_depth : TEXCOORD1; float4 interpolatedRay : TEXCOORD2; } ; v2f vert ( appdata_img v) { v2f o; o. pos = UnityObjectToClipPos ( v. vertex) ; o. uv = v. texcoord; o. uv_depth = v. texcoord; #if UNITY_UV_STARTS_AT_TOP if ( _MainTex_TexelSize. y < 0 ) o. uv_depth. y = 1 - o. uv_depth. y; #endif int index = 0 ; if ( v. texcoord. x < 0.5 && v. texcoord. y < 0.5 ) { index = 0 ; } else if ( v. texcoord. x > 0.5 && v. texcoord. y < 0.5 ) { index = 1 ; } else if ( v. texcoord. x > 0.5 && v. texcoord. y > 0.5 ) { index = 2 ; } else { index = 3 ; } #if UNITY_UV_STARTS_AT_TOP if ( _MainTex_TexelSize. y < 0 ) index = 3 - index; #endif o. interpolatedRay = _FrustumCornersRay[ index] ; return o; } fixed4 frag ( v2f i) : SV_Target { float linearDepth = LinearEyeDepth ( SAMPLE_DEPTH_TEXTURE ( _CameraDepthTexture, i. uv_depth) ) ; float3 worldPos = _WorldSpaceCameraPos + linearDepth * i. interpolatedRay. xyz; float2 speed = _Time. y * float2 ( _FogXSpeed, _FogYSpeed) ; float noise = ( tex2D ( _NoiseTex, i. uv + speed) . r - 0.5 ) * _NoiseAmount; float fogDensity = ( _FogEnd - worldPos. y) / ( _FogEnd - _FogStart) ; fogDensity = saturate ( fogDensity * _FogDensity * ( 1 + noise) ) ; fixed4 finalColor = tex2D ( _MainTex, i. uv) ; finalColor. rgb = lerp ( finalColor. rgb, _FogColor. rgb, fogDensity) ; return finalColor; } ENDCG Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag ENDCG} } FallBack Off
}
效果: