unity shader全局雾效

这篇具有很好参考价值的文章主要介绍了unity shader全局雾效。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

深度纹理

深度纹理存储高精度的深度值,范围为[0,1],而且通常是非线性的。
深度值计算
在顶点变化中,最终会变换到裁剪空间NDC空间下,裁剪空间是一个[-1,1]的线性空间,在NDC空间下我们可以轻松的获得[-1,1]的深度值d
unity shader全局雾效
unity shader全局雾效
获得到d之后,我们将其映射到[0,1]中
unity shader全局雾效
深度值获取
在unity中我们并不需要自己计算深度值,从深度纹理中我们可以获取到深度值。
首先,我们需要通过脚本设置摄像机的depthTextureMode
unity shader全局雾效
设置之后,我们就可以在shader中通过_CameraDepthTexture变量来访问深度纹理。
对深度纹理的采样,为了处理平台差异,使用
unity shader全局雾效
进行采样。
由于采样得到的深度值并不是线性的,我们需要将其变成线性的。
我们知道从视角空间到裁剪空间的变换矩阵,加入我们将一个点从视角空间变化到裁剪空间,我们可以得到:
unity shader全局雾效
将其进行其次除法

unity shader全局雾效
获得表达式
unity shader全局雾效
对其进行映射到[0,1]
unity shader全局雾效

由于摄像机正向对应的z值为负值,所以还要取反
unity shader全局雾效

但是在unity中提供了函数来进行转换
LinearEyeDepth会将深度纹理的采样结果转换到视角空间下的线性深度值
Linear01Depth将会把深度纹理采样结果转换到视角空间下的[0,1]的线性深度值

全局雾效

实现效果

噪声全局雾效

实现关键
我们需要根据深度值,获得每个像素的实际世界坐标。从而模拟全局雾效。

  1. 首先对图像空间下的视锥体射线进行插值,得到摄像机到该像素的方向信息。
  2. 将该射线和线性视角空间下的深度值相乘,得到该点对于摄像机的偏移
  3. 偏移加上世界空间下的摄像机位置得到该点的世界坐标
    代码如下:
    unity shader全局雾效
    _WorldSpaceCameraPos和linearDepth可以由函数求得。
    interpolatedRay计算
    interpolatedRay的计算源自对近裁剪平面四个角的某个特定向量的插值。
    首先我们计算得到近裁剪平面的up、right方向向量
    unity shader全局雾效
    unity shader全局雾效

利用已知的向量表示出摄像机到四个角的向量
unity shader全局雾效
unity shader全局雾效

根据角的向量和深度值,可以求得摄像机到该点的距离
unity shader全局雾效
unity shader全局雾效
提取scale因子
unity shader全局雾效
四个角对应的向量值
unity shader全局雾效
经过这四个向量的插值即可得到interpolatedRay

雾的计算
三种计算雾的计算公式:
unity shader全局雾效
这里我们使用噪声纹理来实现不均匀的雾效
脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FogWithNoise : PostEffectsBase
{
    public Shader fogShader;
    private Material fogMaterial;
    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;
    //噪声纹理
    public Texture noiseTexture;
    //噪声纹理x方向上的移动速度
    [Range(-0.5f, 0.5f)]
    public float fogXSpeed = 0.1f;
    //噪声纹理y方向上的移动速度
    [Range(-0.5f, 0.5f)]
    public float fogYSpeed = 0.1f;
    //噪声纹理的使用程度,如果为0则雾效不受噪声影响
    [Range(0.0f, 3.0f)]
    public float noiseAmount = 1.0f;
    //设置摄像机状态
    private void OnEnable()
    {
        camera.depthTextureMode |= DepthTextureMode.Depth;
    }
    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (material != null)
        {
            //创建存放四个方向变量的矩阵变量
            Matrix4x4 frustumCorners = Matrix4x4.identity;

            //获取到计算所需要的变量
            float fov = camera.fieldOfView;
            float near = camera.nearClipPlane;
            float far = camera.farClipPlane;
            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;
            //scale因子
            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("_FrustumCornersRap", frustumCorners);
            material.SetMatrix("_ViewProjectionInverseMatrix", (camera.projectionMatrix * camera.worldToCameraMatrix).inverse);
            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(source, destination, material);
        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }
}

shader文章来源地址https://www.toymoban.com/news/detail-429486.html

Shader "Custom/Chapter15-FogWithNoise"
{
    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
        _NoiseTex("Noise Texture",2D)="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"

    sampler2D _MainTex;
    half4 _MainTex_TexelSize;
    half _FogDensity;
    fixed4 _FogColor;
    half _FogStart;
    half _FogEnd;
    sampler2D _NoiseTex;
    half _FogXSpeed;
    half _FogYSpeed;
    half _NoiseAmount;
    sampler2D _CameraDepthTexture;
    float4x4 _FrustumCornersRay;

    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
    //计算索引来确定方向变量,后面根据index来获取interpolatedRay
    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 if(v.texcoord.x<0.5 && v.texcoord.y>0.5){
    index=3;
    }

    #if UNITY_UV_STARTS_AT_TOP
    if(_MainTex_TexelSize.y<0){
    index=3-index;
    }
    #endif

    //从_FrustumCornersRay中获取对应index的方向向量
    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;
    //噪声纹理的偏移值
    float2 speed =_Time.y*float2(_FogXSpeed,_FogYSpeed);
    //采样噪声纹理
    float noise =(tex2D(_NoiseTex,i.uv+speed).r-0.5)*_NoiseAmount;

    //根据世界坐标的y值计算雾的浓度
    float fogDensity =(_FogEnd-worldPos.y)/(_FogEnd-_FogStart);//占比值
    //将噪声值加上去,随机的改变雾气的浓度
    fogDensity =(fogDensity*_FogDensity*(1+noise));//雾的浓度

    fixed4 finalColor=tex2D(_MainTex,i.uv);
    //根据雾的浓度来对雾的颜色和本来的颜色做混合
    finalColor.rgb =lerp(finalColor,_FogColor,fogDensity);

    return finalColor;
    }
    ENDCG
    Pass{
    ZTest Always Cull Off ZTest Off
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    ENDCG
    }
    }
    FallBack Off
}

到了这里,关于unity shader全局雾效的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于深度学习的高精度浣熊检测识别系统(PyTorch+Pyside6+模型)

    摘要:基于深度学习的高精度浣熊检测(水牛、犀牛、斑马和大象)识别系统可用于日常生活中或野外来检测与定位浣熊目标,利用深度学习算法可实现图片、视频、摄像头等方式的浣熊目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标

    2024年02月09日
    浏览(51)
  • 基于深度学习的高精度鸡蛋检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度鸡蛋检测识别系统可用于日常生活中或野外来检测与定位鸡蛋目标,利用深度学习算法可实现图片、视频、摄像头等方式的鸡蛋目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用

    2024年02月11日
    浏览(63)
  • 基于深度学习的高精度老虎检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度老虎检测识别系统可用于日常生活中或野外来检测与定位老虎目标,利用深度学习算法可实现图片、视频、摄像头等方式的老虎目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用

    2024年02月12日
    浏览(56)
  • 基于深度学习的高精度绵羊检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度绵羊检测识别系统可用于日常生活中或野外来检测与定位绵羊目标,利用深度学习算法可实现图片、视频、摄像头等方式的绵羊目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用

    2024年02月10日
    浏览(52)
  • 基于深度学习的高精度动物检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度动物检测识别系统可用于日常生活中或野外来检测与定位动物目标(狼、鹿、猪、兔和浣熊),利用深度学习算法可实现图片、视频、摄像头等方式的动物(狼、鹿、猪、兔和浣熊)目标检测识别,另外支持结果可视化与图片或视频检测结果的导

    2024年02月08日
    浏览(85)
  • 基于深度学习的高精度奶牛检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度奶牛检测识别系统可用于日常生活中或野外来检测与定位奶牛目标,利用深度学习算法可实现图片、视频、摄像头等方式的奶牛目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用

    2024年02月08日
    浏览(44)
  • 基于深度学习的高精度猴子检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度猴子检测识别系统可用于日常生活中或野外来检测与定位猴子目标,利用深度学习算法可实现图片、视频、摄像头等方式的猴子目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用

    2024年02月12日
    浏览(74)
  • 基于深度学习的高精度烟雾检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度烟雾检测识别系统可用于日常生活中或野外来检测与定位烟雾目标,利用深度学习算法可实现图片、视频、摄像头等方式的烟雾目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用

    2024年02月11日
    浏览(55)
  • 基于深度学习的高精度刀具检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度刀具检测识别系统可用于日常生活中或野外来检测与定位刀具目标,利用深度学习算法可实现图片、视频、摄像头等方式的刀具目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用

    2024年02月13日
    浏览(48)
  • 基于深度学习的高精度鸽子检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度鸽子检测识别系统可用于日常生活中或野外来检测与定位鸽子目标,利用深度学习算法可实现图片、视频、摄像头等方式的鸽子目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用

    2024年02月09日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包