当前位置: 代码迷 >> 综合 >> 闲云野鹤:吃鸡(二)之场景制作—雾效的制作
  详细解决方案

闲云野鹤:吃鸡(二)之场景制作—雾效的制作

热度:79   发布时间:2023-10-09 09:45:15.0

   试了下unity自带的雾效,感觉最大的问题就是没有包括天空盒,远处处于天空背景的物体显得不真实,如下图。

闲云野鹤:吃鸡(二)之场景制作—雾效的制作

 

因此决定还是自己动手写一个脚本,最终效果如下图:(雾的垂直厚度和水平浓度可调)

闲云野鹤:吃鸡(二)之场景制作—雾效的制作

 

闲云野鹤:吃鸡(二)之场景制作—雾效的制作

思路:很简单,用屏幕后效果实现距离越远雾越浓,但同时从地表向上应该越来越稀薄,不然天空全是雾了,不真实。这主要是shader的作用,脚本很简单,关键代码如下,最后面有3个脚本下载地址。

 

PostEffectsBase.cs(不需要挂在场景物体上)

using UnityEngine;
using System.Collections;[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
//在编辑状态下也可以执行该脚本
public class PostEffectsBase : MonoBehaviour
{protected void CheckResources(){bool isSupported = CheckSupport();if (isSupported == false){NotSupported();}}// 调用CheckResources检查平台上的支持protected bool CheckSupport(){if (SystemInfo.supportsImageEffects == false ){Debug.LogWarning("This platform does not support image effects or render textures.");return false;}return true;}// Called when the platform doesn't support this effectprotected void NotSupported(){enabled = false;}protected void Start(){CheckResources();}protected Material CheckShaderAndCreateMaterial(Shader shader, Material material){if (shader == null){return null;}if (shader.isSupported && material && material.shader == shader)return material;if (!shader.isSupported){return null;}else{material = new Material(shader);material.hideFlags = HideFlags.DontSave;if (material)return material;elsereturn null;}//CheckShaderAndCreateMaterial函数接受两个参数,第一个参数指定了该特效需要使用Shader,//第二个参数则是用于后期处理的材质。该函数首先检查Shader的可用性,检查通过后就返回一个//使用了该Shader的材质,否则返回null。}
}

Fog_global.cs(继承上面的脚本,需要挂在主摄像机上)

using UnityEngine;
using System.Collections;public class Fog_global : PostEffectsBase
{public Shader fogShader;private Material fogMaterial = null;public Material material{get{fogMaterial = CheckShaderAndCreateMaterial(fogShader, fogMaterial);return fogMaterial;}}private Camera myCamera;public new 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, 40.0f)]public float fogDensity = 25.0f;public Color fogColor = Color.white;public float fogStart = 5f;public float fogEnd = 2000f;public float H_floor = -600f;public float H_top = 200f;void OnEnable(){GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;}//首先计算近裁剪平面的4个角对应的向量,并把他们存储在一个矩阵类型的变量)//(frustumCorners)中。 随后把结果和其他参数传递给材质,并调用Graphics.Blit(src,dest,material)//把渲染结果显示在屏幕上。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.SetFloat("_H_floor", H_floor);material.SetFloat("_H_top", H_top);material.SetVector("_CamPos", cameraTransform.position);Graphics.Blit(src, dest, material);}else{Graphics.Blit(src, dest);}}
}

Fog_global.shader(拖入Fog_global.cs槽中)

Shader "custom/Fog" {Properties {_MainTex ("Base (RGB)", 2D) = "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}SubShader {CGINCLUDE#include "UnityCG.cginc"float4x4 _FrustumCornersRay;sampler2D _MainTex;half4 _MainTex_TexelSize;//深度纹理sampler2D _CameraDepthTexture;half _FogDensity;fixed4 _FogColor;float _FogStart;float _FogEnd;float4 _CamPos;float _H_floor;float _H_top;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_TOPif (_MainTex_TexelSize.y < 0)o.uv_depth.y = 1 - o.uv_depth.y;#endifint 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_TOPif (_MainTex_TexelSize.y < 0)index = 3 - index;#endifo.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;float _distance = distance(worldPos,_CamPos);float fogDensity = (_distance-_FogStart)*0.3 / (_FogEnd - _FogStart); //越远越浓fogDensity *=(_H_top - worldPos.y) / (_H_top - _H_floor);//离地面越高越稀薄fogDensity = saturate(fogDensity * _FogDensity) ;fixed4 finalColor= tex2D(_MainTex, i.uv);finalColor.rgb = lerp(finalColor.rgb, _FogColor.rgb, fogDensity*0.3);return finalColor ;}ENDCGPass {              CGPROGRAM  #pragma vertex vert  #pragma fragment frag  ENDCG}} FallBack Off
}

全部脚本下载地址:https://download.csdn.net/download/qq_34593121/11977887

下载内容说明:unity自带的雾效,感觉最大的问题就是没有包括天空盒,远处处于天空背景的物体显得不真实,此脚本可以用屏幕后效果实现距离越远雾越浓,同时从地表向上越来越稀薄,形成比较自然的雾效。