Shader学习的基础知识(二十七)全局雾效
2019-03-15 19:13
337 查看
版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ww1351646544/article/details/88580822
烟雾的原理
烟雾效果是基于距离的线性或指数增长的效果。
我们在Shader中添加#pragma multi_compile_fog同时还要使用UNITY_FOG_COORDS、UNITY_TRANSFER_FOG、UNITY_APPLY_FOG等。这方法缺点在于要场景里所有的Shader添加,而且能够实现的效果也有限。
所以我们选择使用屏幕后处理来实现,其关键点即是根据每个深度纹理来构建每个像素在世界坐标下的位置。
首先是从摄像机出发向每个像素点发出射线并对射到的点进行插值,这条射线记录了世界空间下到摄像机的方向信息。然后我们把射线和线性化后的视角下的深度值相乘,再加上摄像机的世界位置,就可以得到该像素在下的位置。就可以用各种公式来模拟全局雾效了。
重建世界坐标
一个点位置可以通过它相对于另一个点的坐标偏移到求得,所以我们只要知道摄像机世界空间的位置以及世界空间下像素相对于摄像机的偏移量,把它们相加就可以得到该像素的世界空间下坐标了,即:
float4 worldPos = _WorldSpaceCameraPos+linearDepth*interpolatedRay;
_WorldSpaceCameraPos:世界空间摄像机位置
linearDepth:深度纹理得到的线性深度值
interpolatedRay:顶点着色器输出并插值后得到的射线
雾的计算
float afterFog = f*fogColor+(1-f)*origColor;
f为烟雾系数,fogColor烟雾色,origColor是原来的颜色
实例
摄像机上脚本:
using UnityEngine; using System.Collections; public class FogWithDepthTexture : 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.0f, 3.0f)] public float fogDensity = 1.0f; public Color fogColor = Color.white; public float fogStart = 0.0f; public float fogEnd = 2.0f; void OnEnable() { 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); Graphics.Blit (src, dest, material); } else { Graphics.Blit(src, dest); } } }
基类
using UnityEngine; using System.Collections; [ExecuteInEditMode] [RequireComponent (typeof(Camera))] public class PostEffectsBase : MonoBehaviour { //检查各种资源是否满足,我们调用 protected void CheckResources() { bool isSupported = CheckSupport(); if (isSupported == false) { NotSupported(); } } //检查是否支持 protected bool CheckSupport() { if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false) { Debug.LogWarning("This platform does not support image effects or render textures."); return false; } return true; } //不支持的处理 protected void NotSupported() { enabled = false; } protected void Start() { CheckResources(); } /// <summary> /// 后期处理 /// </summary> /// <param name="shader">该特效使用的Shader</param> /// <param name="material">用于处理的材质</param> /// <returns></returns> 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; else return null; } } }
Shader部分脚本
Shader "Custom/TestShader31" { 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; struct v2f { float4 pos : SV_POSITION; half2 uv : TEXCOORD0; half2 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; float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart); fogDensity = saturate(fogDensity * _FogDensity); fixed4 finalColor = tex2D(_MainTex, i.uv); finalColor.rgb = lerp(finalColor.rgb, _FogColor.rgb, fogDensity); return finalColor; } ENDCG Pass { ZTest Always Cull Off ZWrite Off CGPROGRAM #pragma vertex vert #pragma fragment frag ENDCG } } FallBack Off }24000
相关文章推荐
- Shader学习的基础知识( 三十三)渲染优化具体
- Shader学习的基础知识(五)渐变纹理
- Shader学习的基础知识( 三十四)表面着色器上
- Node.js学习--基础知识(8)--全局对象和全局变量
- Shader学习的基础知识(二十八)卡通风格渲染
- Shader学习的基础知识(二十九)素描风格渲染
- Shader学习的基础知识( 三十一)水波效果
- Shader学习的基础知识(四)法线贴图
- Shader学习的基础知识( 三十二)渲染优化概括
- 深度学习FPGA实现基础知识13(向专家致敬--深度学习-LeCun、Bengio和Hinton的联合综述)
- 学习 shell脚本之前的基础知识
- javaScript学习基础知识汇总
- JS学习2(基础知识)
- 【Java学习笔记】基础知识学习10【继承与多态】
- [Python学习] 专题四.文件基础知识
- ARM学习笔记——Linux基础知识
- Solaris学习笔记:8.SSH配置(1.ssh基础知识)
- 学习笔记之C#类、循环中的语句、基础知识和异常处理
- oracle数据库基础知识学习笔记
- HTML/CSS基础知识学习笔记