Unity中Shader雾效的实现方法一

news/2024/7/24 13:36:01 标签: unity, 游戏引擎

文章目录

  • 前言
  • 一、在片元着色器中使用如下公式计算
    • `最终的颜色 = lerp(雾效颜色,物体颜色,雾效混合因子)`
    • 1、获取雾效颜色
    • 2、物体的颜色一般通过纹理采样得到,此处用 1 代替测试
    • 3、获取 雾效混合因子(由 雾的距离 和 雾的浓度决定)
  • 二、在顶点着色器中,计算不同类型的雾效混合因子(在顶点着色器计算节省性能)
    • Unity预定义好方便我们计算的四维变量 unity_FogParams
    • 1、计算线性雾的雾效混合因子
    • 2、计算指数雾1 的雾效混合因子
    • 3、计算指数雾2 的雾效混合因子
  • 三、最终测试代码


前言

Unity中Shader雾效的实现方法一,按照之前的公式, 我们自己来实现一下

  • Unity中Shader雾效的原理

基于上一篇文章继续:

  • Unity中Shader的雾效

一、在片元着色器中使用如下公式计算

最终的颜色 = lerp(雾效颜色,物体颜色,雾效混合因子)

不管是什么类型的雾,这个雾效的公式都是统一的

1、获取雾效颜色

unity_FogColor

2、物体的颜色一般通过纹理采样得到,此处用 1 代替测试

3、获取 雾效混合因子(由 雾的距离 和 雾的浓度决定)

雾效混合因子是由,之前的三个雾效衰减公式计算得到的

  • Unity中Shader雾效的原理

因为在片元着色器中计算雾效需要使用该因子
所以在 v2f 中定义一个 TEXCOORD 类型的 float 变量 fogFactor

float fogFactor : TEXCOORD1;


二、在顶点着色器中,计算不同类型的雾效混合因子(在顶点着色器计算节省性能)

unity_FogParams_35">Unity预定义好方便我们计算的四维变量 unity_FogParams

在这里插入图片描述

1、计算线性雾的雾效混合因子

在这里插入图片描述

  • 获取 z :这个z是摄像机到物体的距离
    z = (用摄像机的世界坐标 - 顶点的世界坐标)的 模长
    计算需要准备:
    摄像机的世界坐标:_WorldSpaceCameraPos
    顶点的世界坐标:mul(unity_ObjectToWorld,v.vertex)

float z = length(_WorldSpaceCameraPos - worldPos);

  • 获取 start 和 end
    上面的公式可以等价为:
    fogFactor
    = (end - z) / (end - start)
    = (end / (end - start)) + z * (-1 / (end - start))
    使用Unity预定义的公式后:
    = unity_FogParams.w + z * unity_FogParams.z ;

//(end - z) / (end - start)= (end / (end - start)) + z * (-1 / (end - start))
o.fogFactor = z * unity_FogParams.z + unity_FogParams.w;

效果:
请添加图片描述

2、计算指数雾1 的雾效混合因子

在这里插入图片描述

fogFactor
= exp2(-density * z)
使用Unity预定义的公式后:
= exp2(-unity_FogParams.y * z)

//exp2(-density * z)
o.fogFactor = exp2(-unity_FogParams.y * z);

效果:
请添加图片描述

3、计算指数雾2 的雾效混合因子

在这里插入图片描述
fogFactor
= exp2(-(density * z)^2)
使用Unity预定义的公式后:
= exp2(-(unity_FogParams.x * z)^2)

//exp2(-(density * z)^2)
float density = unity_FogParams.x * z;
o.fogFactor = exp2(-density * density);

效果:
请添加图片描述


三、最终测试代码

//unity的雾效
//雾效的实现方法一
Shader "MyShader/P1_9_3"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            #include "UnityCG.cginc"
           

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float fogFactor : TEXCOORD1;
            };
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                float4 worldPos = mul(unity_ObjectToWorld,v.vertex);
                float z = length(_WorldSpaceCameraPos - worldPos);

                #if defined(FOG_LINEAR)
                    //(end - z) / (end - start)= (end / (end - start)) + z * (-1 / (end - start))
                    o.fogFactor = z * unity_FogParams.z + unity_FogParams.w;
                #elif defined(FOG_EXP)
                    //exp2(-density * z)
                    o.fogFactor = exp2(-unity_FogParams.y * z);
                #elif defined(FOG_EXP2)
                    //exp2(-(density * z)^2)
                    float density = unity_FogParams.x * z;
                    o.fogFactor = exp2(-density * density);
                #endif
                
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 c = 0;
                #if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
                    c = lerp(unity_FogColor,c,i.fogFactor);
                #endif
                
                return c;
            }
            ENDCG
        }
    }
}


http://www.niftyadmin.cn/n/5174984.html

相关文章

Java 8 Stream 的使用场景

Java 8 Stream 的使用场景 只符合所筛选条件至多一条 CommonArea l common.stream().filter(item ->item.getName().equals("aa")).findAny().orElse(null);返回多条记录 List<Object> list common.stream().filter(item -> item.getName().equals(&…

【Linux】【驱动】设备树下的paltform总线

【Linux】【驱动】设备树下的paltform总线 1. 驱动程序的完整代码2. 使用到的相关函数3 使用到的指令3.2 设备上使用的指令 1. 驱动程序的完整代码 主要是展示了通过总线上挂载的方式来实现相关的数据读取 实质上就是几个of函数的调用。 /** Author: topeet* Description: 设…

【debug】解决Kali虚拟机开机黑屏,左上角光标一直闪动无法开机问题

做网络攻防实验时&#xff0c;突然Kali无法打开&#xff0c;遇到这个问题。。。。。。 遇到的问题 突然kali虚拟机变成如下黑屏&#xff0c;无法开机&#xff0c;左上角光标闪动&#xff0c;重启无效。 解决办法 在上图界面&#xff0c;按Ctrl F3&#xff08;不同电脑快捷键…

线性代数理解笔记

一.向量引入: 向量&#xff1a;只由大小和方向决定&#xff0c;不由位置决定。 二.向量加减法 向量的加法是首尾相连&#xff0c;减法是尾尾相连。 而向量v向量w为平行四边形主对角线。 向量v-向量w为平行四边形副对角线。 2.向量内积点乘&#xff08;内积&#xff09; 内积…

C#操作注册表的方法

注册表是Microsoft Windows操作系统中的一个重要组成部分&#xff0c;用于存储和管理系统和应用程序的配置信息。它是一个层次结构的数据库&#xff0c;以树形结构组织&#xff0c;类似于文件系统中的文件夹和文件。 注册表存储了许多与操作系统和软件相关的信息&#…

问答推广怎么做?问答口碑营销的优势有哪些?

互联网问答平台上线以来&#xff0c;问答口碑营销一直是企业进行网络营销推广不可缺少的一种方式&#xff0c;那么&#xff0c;什么是问答营销推广呢&#xff1f;如何开展问答营销推广&#xff1f;问答营销有哪些优势呢&#xff1f;小马识途营销顾问在本文分析一下。 什么是问答…

用python随机生成座位表

1 问题 学习中总会遇到大大小小的考试&#xff0c;考试场地和考试座位的确立是考试准备工作的重要一环&#xff0c;那么能否用python随机生成座位表呢。 2 方法 定义座位表的行列数&#xff0c;例如10行10列创建一个二维数组&#xff0c;用于存储座位信息&#xff0c;例如使用0…

双编码器构建机器人零力拖动/导纳控制思路

前言 这篇博客主要记录昨日与实验室大佬针对UR5机器人拖动示教功能实现的思路。由于本人并非主攻力控方面。直到昨天在做实验的时候&#xff0c;与力控组的大佬讨论过后才了解UR机器人实现导纳控制的思路。 关于导纳控制/零力拖动 导纳控制与阻抗控制单从字面去理解很容易记…