Unity中Shader阴影的投射

news2024/10/6 16:28:34

文章目录

  • 前言
  • 一、我们急需使用之前 Offset 中的Shader作为测试
  • 二、生成阴影
    • 1、添加"LightMode" = "ShadowCaster"的Pass.
    • 2、appdata中声明float4 vertex:POSITION;和half3 normal:NORMAL;这是生成阴影所需要的语义.
    • 3、v2f中添加V2F_SHADOW_CASTER;用于声明需要传送到片断的数据.
    • 4、在顶点着色器中添加TRANSFER_SHADOW_CASTER_NORMALOFFSET(o),主要是计算阴影的偏移以解决不正确的Shadow Acne和Peter Panning现象.
    • 5、在片断着色器中添加SHADOW_CASTER_FRAGMENT(i)
  • 三、让影子和小狐狸一起随着消融而变化
    • 1、可以复用之前小狐狸消融的逻辑


前言

Unity中Shader阴影的投射


一、我们急需使用之前 Offset 中的Shader作为测试

Unity中Shader的深度偏移Offset

我们会发现,此时的小狐狸没有影子。这是因为我们的Shader中,并没有写阴影的投射。
在这里插入图片描述


二、生成阴影

1、添加"LightMode" = "ShadowCaster"的Pass.

Tags{“LightMode” = “ShadowCaster”}

需要添加一个 Unity变体请添加图片描述

#pragma multi_compile_shadowcaster
定义在LightMode=ShadowCaster的Pass中,会自动生成两个宏:

  1. SHADOWS_DEPTH :用于生成直线光和聚光灯阴影.
  2. SHADOW_CUBE :用于生成点光源阴影.

2、appdata中声明float4 vertex:POSITION;和half3 normal:NORMAL;这是生成阴影所需要的语义.

注意:在appdata部分,我们几乎不要去修改名字 和 对应的类型。
因为,在Unity中封装好的很多方法都是使用这些标准的名字 和 类型

struct appdata
{
float4 vertex:POSITION;
half3 normal:NORMAL;
};

3、v2f中添加V2F_SHADOW_CASTER;用于声明需要传送到片断的数据.

struct v2f
{
V2F_SHADOW_CASTER;
};

4、在顶点着色器中添加TRANSFER_SHADOW_CASTER_NORMALOFFSET(o),主要是计算阴影的偏移以解决不正确的Shadow Acne和Peter Panning现象.

v2f vert(appdata v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
return o;
}

5、在片断着色器中添加SHADOW_CASTER_FRAGMENT(i)

fixed4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i);
}

可以看见,我们的小狐狸现在已经有了影子
请添加图片描述
这样写好后,我们可以在 Mesh Renderer 中控制,是否投下阴影
请添加图片描述


三、让影子和小狐狸一起随着消融而变化

1、可以复用之前小狐狸消融的逻辑

最终代码:

Shader "MyShader/P1_7_2"
{
    Properties
    {
        [Enum(Off,0,On,1)]_ZWrite("ZWrite",int) = 0
        [Enum(UnityEngine.Rendering.CompareFunction)]_ZTest("ZTest",int) = 0
        //使用这个标签,可以使外部暴露属性,有标题
        [Header(Base)]
        [NoScaleOffset]_MainTex ("Texture", 2D) = "white" {}
        _Clip("Clip",Range(0,1)) = 0
        //使用这个标签可以 在两行暴露属性之间加 间隙
        [Space(10)]
        [Header(Dissolve)]
        _DissolveTex("DissolveTex",2D) = "black"{}

        [NoScaleOffset]_RampTex("RampTex(RGB)",2D) = "black" {}
        
    }
    SubShader
    {
        Tags{"Queue" = "Geometry"}
        Blend Off
        Cull Back
        /*ZWrite [_ZWrite]
        
        ZTest [_ZTest]*/
        
        Offset -1,-1
        
        UsePass "MyShader/P1_6_4/XRay"
        
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            
            sampler2D _MainTex;
            float _Clip;
            sampler2D _DissolveTex; 
            //这个四维向量,xyzw分别表示 Tilling 和 Offset 的 xy ,命名方式 在纹理名 后加 _ST
            float4 _DissolveTex_ST;


            //因为 在使用渐变纹理时,只使用了 渐变纹理的 u 坐标,所以把  sampler2D 换为 sampler
            sampler _RampTex;

            struct appdata
            {
                float4 vertex : POSITION;
                float4 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 uv : TEXCOORD0;
                float4 pos : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                
                //为了减少传入的值 ,所以就不创建新变量来存储,而是把 uv 改为  四维向量 来用
                //使用 o.uv 的 xy 来存放 原人物贴图
                //使用 o.uv 的 zw 来存放 噪波贴图缩放 和 偏移 后的值
                o.uv.xy = v.uv.xy;
                //o.uv.zw = v.uv * _DissolveTex_ST.xy + _DissolveTex_ST.zw;

                o.uv.zw = TRANSFORM_TEX(v.uv,_DissolveTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv.xy);
                //外部获取的 纹理 ,使用前都需要采样
                fixed4 dissolveTex = tex2D(_DissolveTex,i.uv.zw);
                
                //片段的取舍
                clip(dissolveTex.r -  _Clip);

                //进行归一化
                fixed4 dissolveValue = saturate((dissolveTex.r - _Clip) / (_Clip + 0.1 - _Clip));

                fixed4 rampTex = tex1D(_RampTex,dissolveValue.r);

                //col += rampTex;
                return col;
            }
            ENDCG
        }
        //阴影的投射
        Pass
        {
            //1、设置 "LightMode" = "ShadowCaster"
            Tags{"LightMode" = "ShadowCaster"}
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag
            //需要添加一个 Unity变体
            #pragma multi_compile_shadowcaster

            
            #include "UnityCG.cginc"

            //声明消融使用的变量
            float _Clip;
            sampler2D _DissolveTex;
            float4 _DissolveTex_ST;
            
            //2、appdata中声明float4 vertex:POSITION;和half3 normal:NORMAL;这是生成阴影所需要的语义.
            //注意:在appdata部分,我们几乎不要去修改名字 和 对应的类型。
            //因为,在Unity中封装好的很多方法都是使用这些标准的名字
            struct appdata
            {
                float4 vertex:POSITION;
                half3 normal:NORMAL;
                float4 uv:TEXCOORD;
            };
            //3、v2f中添加V2F_SHADOW_CASTER;用于声明需要传送到片断的数据.
            struct v2f
            {
                float4 uv : TEXCOORD;
                V2F_SHADOW_CASTER;
            };
            //4、在顶点着色器中添加TRANSFER_SHADOW_CASTER_NORMALOFFSET(o),主要是计算阴影的偏移以解决不正确的Shadow Acne和Peter Panning现象.
            v2f vert(appdata v)
            {
                v2f o;
                o.uv.zw = TRANSFORM_TEX(v.uv,_DissolveTex);
                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
                return o;
            }
            //5、在片断着色器中添加SHADOW_CASTER_FRAGMENT(i)
            
            fixed4 frag(v2f i) : SV_Target
            {
                //外部获取的 纹理 ,使用前都需要采样
                fixed4 dissolveTex = tex2D(_DissolveTex,i.uv.zw);
                
                //片段的取舍
                clip(dissolveTex.r -  _Clip);
                
                SHADOW_CASTER_FRAGMENT(i);
            }
            ENDCG
        }
    }
}

最后我们看见,影子随着小狐狸消融 也同时消融了
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1117681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java 通用导出接口

每个功能导出文件都单独写接口太过繁琐,出于方便大致讲讲通用导出功能的实现。 导出文件配置表,该表保存导出dto和导出文件名的对应关系等信息: TableName(value "SIMPLE_COMMON_EXPORT_TAB") public class SimpleCommonExportT…

vue3+element-plus 封装列表页,分页,排序,导出

目录 背景描述: 开发流程: 详细开发: 总结: 背景描述: web很多时候,要开发一个列表页,展示大量数据,并且提供一些交互功能,例如排序和分页,导出功能&…

嵌入式硬件库的基本操作方式与分析

本次要介绍的开源软件是 c-periphery: https://github.com/vsergeev/c-periphery一个用 C 语言编写的硬件外设访问库。 我们可以用它来读写 Serial、SPI、I2C 等,非常适合在嵌入式产品上使用。 我们可以基于它优秀的代码框架,不断地扩展出更…

高斯分布与高斯过程

一元高斯分布 我们从最简单最常见的一元高斯分布开始,其概率密度函数为: p ( x ) 1 σ 2 π e x p ( − ( x − μ ) 2 2 σ 2 ) p(x)\frac{1}{\sigma\sqrt{2\pi}}exp(-\frac{(x-\mu)^2}{2\sigma^2}) p(x)σ2π ​1​exp(−2σ2(x−μ)2​) 其中 μ \…

2023年中职组“网络安全”赛项云南省竞赛任务书

2023年中职组“网络安全”赛项 云南省竞赛任务书 一、竞赛时间 总计:360分钟 竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 A模块 A-1 登录安全加固 180分钟 200分 A-2 本地安全策略配置 A-3 流量完整性保护 A-4 事件监控 A-5 服务加固…

python接口自动化测试 —— unittest框架suite、runner详细使用

test suite 测试套件,理解成测试用例集一系列的测试用例,或测试套件,理解成测试用例的集合和测试套件的集合当运行测试套件时,则运行里面添加的所有测试用例 test runner 测试运行器用于执行和输出结果的组件 test suite、tes…

HP OfficeJet Pro 8020 如何更换碳粉盒

环境: HP OfficeJet Pro 8020 问题描述: HP OfficeJet Pro 8020 如何更换碳粉盒 解决方案: 更换碳粉盒 更换所有墨水不足的碳粉盒或空碳粉盒。 1.打开前挡盖,然后提起碳粉盒检修门。 打开打印机门 2.等待笔架停止后再继续操作…

外贸人必备的跨境电商常见专有名词!

不管我们在做跨境电商运营、广告或者物流的时候总会遇到很多专有名词或者缩写,但我们接收信息又总是很零散的、不系统的。 所以这边为大家详细整理了常见的专有名词,大家可以保存下来不懂的时候实时查阅噢~ 01 什么是跨境电商 跨境电商是指分属不同关境…

【C++入门系列】——类和对象

​作者主页 📚lovewold少个r博客主页 ⚠️本文重点:C入门知识点以及类和对象的初步了解 😄每日一言:实践能力是自学能力最终转化为真正价值的根本。 目录 前言 auto关键字 auto关键字新用法 auto使用细节 auto与指针和引用结…

VisualStudio(VS)设置程序的版本信息(C-C++)

一、前言 在软件开发过程中,通常需要为生成的程序添加一些重要的元数据,如版本号、公司名称和版权信息。这些信息不仅可以提供对程序的更详细描述,还可以帮助用户了解程序的来源和使用限制。在 Visual Studio (以2017为例)中,可以…

大数据请把这个分离软件推给所有后期~

相信每个后期都要这样一个烦恼,怎样单独提取人声台词?怎么样提取背景音乐,今天就给大家推荐一款超实用的人声分离软件,可以在线提取人声或背景音乐,对于做后期的小伙伴们来说简直就是神器,再也不用到处找音…

C语言指针精简版(三)

目录 字符指针变量 剑指offer中经典题: 数组指针变量 ⼆维数组传参的本质 函数指针变量 typedef关键字 函数指针数组 什么是函数指针数组? 为什么要使用函数指针数组? 转移表 计算器的⼀般实现: 使用函数指针实现&…

MyBatisPlus(二十二)代码生成器

使用场景 使用代码生成器&#xff0c;根据数据库表&#xff0c;自动生成对应的 Entity&#xff0c;Mapper&#xff0c;Service&#xff0c;Controller 。 代码 依赖 两个依赖&#xff1a; 生成器依赖模板依赖 <dependency><groupId>com.baomidou</groupId&…

思维导图Xmind2023安装教程分享

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;xmind 获取 1、解压压缩包得到以下文件。 2、如果“winmm.dll”被系统删除不见&#xff0c;打开屏幕右下角处“windows安全中心”&#xff0c;在历史记录里将已删除的还原即可。 3、以管理员身份打开“Setup”。 4、…

Win10如何彻底关闭wsappx进程?

Win10如何彻底关闭wsappx进程&#xff1f;在Win10电脑中&#xff0c;用户看到了wsappx进程占用了大量的系统资源&#xff0c;所以想结束wsappx进程&#xff0c;提升电脑的运行速度。但是&#xff0c;用户们不知道彻底关闭掉wsappx进程的方法&#xff0c;那么接下来小编就给大家…

windows编译zlmediakit

开发环境搭建 使用visual studio 2022 打开360软件管家 &#xff0c;选择宝库&#xff0c;输入2022 点击安装 选择下图中的选择项目进行安装&#xff0c;安装路径可以修改为d盘 等待安装完成 打开源码进行编译 双击打开 选择打开文件夹 选择代码文件夹 配置如下&#xff…

视频播放音画同步处理

一、视频播放流程 播放一个视频&#xff0c;一般分一下几步完成 解复用&#xff08;Demux&#xff09;&#xff1a;在媒体文件中将音频数据、视频数据、字母数据分离出来。 二、播放参数说明 视频帧率&#xff1a;一秒钟需要显示的画面&#xff0c;比如25FPS&#xff0c;意思就…

sql注入的其他注入

1.宽字节注入 原因 绕过单双引号转义 ?id1 ?id1 1\ 服务器会把单引号转义&#xff0c;单引号由原来的定义字符串的特殊字符被转义为普通字符。 315c27 非常强烈的暗示 代码 单双引号转义 并且编码变成了gbk 上编码 表 这个是GBK编码表&#xff1a;https://…

可变参数模板+lambda

目录 可变参数模板 引入 介绍 展开参数包的方法 递归 逗号表达式 整体使用 emplace 介绍 ​编辑 使用 模拟实现 代码 示例 lambda 引入 介绍 格式 使用 传参 捕捉 原理 可变参数模板 引入 还记得c语言中的printf吗,可以传入任意数量的变量来打印,非常…