【Unity Shader入门精要 第9章】更复杂的光照(四)

1. 透明度测试物体的阴影

对于物体有片元丢弃的情况,比如透明度测试或者后边会讲到的消融效果,使用默认的 ShadowCaster Pass 会产生问题,这是因为该Pass在生成阴影映射纹理时,没有考虑被丢弃的片元,而是使用完整的模型计算深度,因此镂空的部分也会向外投射阴影。

要解决这个问题,可以使用Unity内置的Pass:

UsePass "Legacy Shaders/Transparent/Cutout/VertexLit/CASTER"

由于该Pass内部在计算阴影时需要用到特定名称的变量,因此在使用时,必须声明如下属性:

Properties
{_MainTex("MainTex", 2D) = "white"{}_Color("Color", Color) = (1, 1, 1, 1)_Cutoff("Cutoff", range(0, 1)) = 0}

除此以外,我们也可以自己实现一个 ShadowCaster 的 Pass,代码与上一篇【Unity Shader入门精要 第9章】更复杂的光照(三)中手动实现的 ShadowCaster 基本一样,只是在片元着色器中加入和正常渲染 Pass 中一样的剔除代码即可。

另外,由于镂空物体的内部也可能产生阴影,因此根据需要可以将物体的Cast Shadows选项选为Two Sided
在这里插入图片描述

测试Shader如下:

Shader "MyShader/Chapter_9/Chapter_9_Shadow_AlphaTest_Shader"
{Properties{_MainTex("MainTex", 2D) = "white"{}_Color("Color", Color) = (1, 1, 1, 1)_Cutoff("Cutoff", range(0, 1)) = 0}SubShader{Tags {"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}Pass{Tags {"LightMode" = "ForwardBase"}Cull FrontCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#include "Lighting.cginc"#include "AutoLight.cginc"#pragma multi_compile_fwdbasestruct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;SHADOW_COORDS(3)};sampler2D _MainTex;float4 _MainTex_ST;fixed _Cutoff;v2f vert(a2v i){v2f o;o.pos = UnityObjectToClipPos(i.vertex);o.worldNormal = mul(i.normal, (float3x3)unity_WorldToObject);o.uv = TRANSFORM_TEX(i.uv, _MainTex);o.worldPos = mul(unity_ObjectToWorld, i.vertex).xyz;TRANSFER_SHADOW(o);return o;}fixed4 frag(v2f i) : SV_Target{float3 _worldNormal = normalize(i.worldNormal);float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);fixed4 _sampledColor = tex2D(_MainTex, i.uv);clip(_sampledColor.w - _Cutoff);fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;fixed3 _diffuse = _LightColor0.rgb * _sampledColor.xyz * (0.5 * dot(_worldLight, _worldNormal) + 0.5);UNITY_LIGHT_ATTENUATION(_atten, i, i.worldPos);return fixed4(_ambient + _diffuse * _atten, 1);}ENDCG}Pass{Tags {"LightMode" = "ForwardBase"}Cull BackCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#include "Lighting.cginc"#include "AutoLight.cginc"#pragma multi_compile_fwdbasestruct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;SHADOW_COORDS(3)};sampler2D _MainTex;float4 _MainTex_ST;fixed _Cutoff;v2f vert(a2v i){v2f o;o.pos = UnityObjectToClipPos(i.vertex);o.worldNormal = mul(i.normal, (float3x3)unity_WorldToObject);o.uv = TRANSFORM_TEX(i.uv, _MainTex);o.worldPos = mul(unity_ObjectToWorld, i.vertex).xyz;TRANSFER_SHADOW(o);return o;}fixed4 frag(v2f i) : SV_Target{fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;float3 _worldNormal = normalize(i.worldNormal);float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);fixed4 _sampledColor = tex2D(_MainTex, i.uv);clip(_sampledColor.w - _Cutoff);fixed3 _diffuse = _LightColor0.rgb * _sampledColor.xyz * (0.5 * dot(_worldLight, _worldNormal) + 0.5);UNITY_LIGHT_ATTENUATION(_atten, i, i.worldPos);return fixed4(_ambient + _diffuse * _atten, 1);}ENDCG}//使用内置的Pass处理透明度测试的物体向外投射阴影//UsePass "Legacy Shaders/Transparent/Cutout/VertexLit/CASTER"//或者根据渲染逻辑手动实现符合当前效果的ShadowCaster的PassPass{Tags { "LightMode" = "ShadowCaster" }CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#pragma multi_compile_shadowcasterstruct a2v{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;};struct v2f{V2F_SHADOW_CASTER;float2 uv : TEXCOORD0;};sampler2D _MainTex;float4 _MainTex_ST;fixed _Cutoff;v2f vert(a2v v){v2f o;o.uv = TRANSFORM_TEX(v.uv, _MainTex);TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);return o;}fixed4 frag(v2f i) : SV_Target{fixed4 _sampledColor = tex2D(_MainTex, i.uv);clip(_sampledColor.w - _Cutoff);SHADOW_CASTER_FRAGMENT(i);}ENDCG            }}}

效果如下:
在这里插入图片描述

2. 透明度混合物体的阴影

2.1 投射阴影

透明度混合的Shader中关闭了深度写入,不会参与深度纹理的计算,因此不会向其他物体投射阴影。要使透明度测试的物体能够向外投射阴影方法有很多,比如放一个直接算阴影但不渲染自身的代替物体,或者像书中说的添加一个非Transparent的FallBack的Shader,再或者自己手写一个,都可以实现。

下面的例子就是将之前的阴影投射的Pass复制过来,也可以正常产生阴影。

Shader "MyShader/Chapter_9/Chapter_9_Shadow_AlphaBlend_Shader"
{Properties{_MainTex("MainTex", 2D) = "white"{}}SubShader{Tags { "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True"}Pass{Tags {"LightMode" = "ForwardBase"}Cull FrontZWrite OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdbase#include "UnityCG.cginc"#include "Lighting.cginc"#include "AutoLight.cginc"struct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;SHADOW_COORDS(3)};sampler2D _MainTex;float4 _MainTex_ST;v2f vert(a2v i){v2f o;o.pos = UnityObjectToClipPos(i.vertex);o.worldNormal = UnityObjectToWorldNormal(i.normal);o.worldPos = mul(unity_ObjectToWorld, i.vertex).xyz;o.uv = TRANSFORM_TEX(i.uv, _MainTex);TRANSFER_SHADOW(o);return o;}fixed4 frag(v2f i) : SV_Target{fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;float3 _worldNormal = normalize(i.worldNormal);float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);float4 _mainColor = tex2D(_MainTex, i.uv);fixed3 _diffuse = _LightColor0.rgb * _mainColor.xyz * (0.5 * dot(_worldLight, _worldNormal) + 0.5);UNITY_LIGHT_ATTENUATION(_atten, i, i.worldPos);return fixed4(_ambient + _diffuse * _atten, _mainColor.w);}ENDCG}Pass{Tags {"LightMode" = "ForwardBase"}Cull BackZWrite OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdbase#include "UnityCG.cginc"#include "Lighting.cginc"#include "AutoLight.cginc"struct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;SHADOW_COORDS(3)};sampler2D _MainTex;float4 _MainTex_ST;v2f vert(a2v i){v2f o;o.pos = UnityObjectToClipPos(i.vertex);o.worldNormal = UnityObjectToWorldNormal(i.normal);o.worldPos = mul(unity_ObjectToWorld, i.vertex).xyz;o.uv = TRANSFORM_TEX(i.uv, _MainTex);TRANSFER_SHADOW(o);return o;}fixed4 frag(v2f i) : SV_Target{fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;float3 _worldNormal = normalize(i.worldNormal);float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);float4 _mainColor = tex2D(_MainTex, i.uv);fixed3 _diffuse = _LightColor0.rgb * _mainColor.xyz * (0.5 * dot(_worldLight, _worldNormal) + 0.5);UNITY_LIGHT_ATTENUATION(_atten, i, i.worldPos);return fixed4(_ambient + _diffuse * _atten, _mainColor.w);}ENDCG}Pass{Tags { "LightMode" = "ShadowCaster" }CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#pragma multi_compile_shadowcasterstruct v2f{V2F_SHADOW_CASTER;};v2f vert(appdata_base v){v2f o;TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);return o;}fixed4 frag(v2f i) : SV_Target{SHADOW_CASTER_FRAGMENT(i);}ENDCG}}//    FallBack "VertexLit"
//    FallBack "Diffuse"
}

效果:
在这里插入图片描述

2.2 接收阴影

半透物体接收阴影就比较麻烦了,即使像书中说的将FallBack设置为 VertexLit,实际也是无法接收到阴影的(可以将上面测试shader中的注释放开试一下)。

这是因为正常半透物体的渲染队列为3000(Transparent),而在2500以后就没有阴影映射纹理的信息了,因此即使shader里有相应代码,也无法正常接收到阴影。

从下面 FrameDebug 的截图中也可以看出来:
在这里插入图片描述
网上最多的说法是将渲染队列强制调到2500以下,比如像这样:
在这里插入图片描述
在这里插入图片描述
这样虽然能接收到阴影,但显然不是正经做法,因为这样会造成半透物体的渲染顺序错乱,比如这样:
在这里插入图片描述
要真正解决这个问题,内容就超出《入门精要》的范围了(也超出我的范围了)。
这里先存本书,《实时阴影技术》,有时间开坑研究一下(应该是不会有时间了)。

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

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

相关文章

建投数据收获客户感谢信

建投数据自2021年提出“以数据为核心的智能科技服务商”,并一直在为“成为国内领先的数字化转型合作伙伴”而努力,在赋能行业客户创造更大价值的同时,也陆续收到来自客户的肯定。 建投数据始终践行“成就客户,创新为要&#xff0…

【网络协议】【OSI】一次HTTP请求OSI工作过程详细解析

目录 1. 一次HTTP请求OSI工作过程 1.1 应用层(第7层) 1.2 表示层(第6层) 1.3 会话层(第5层) 1.4 传输层(第4层) 1.5 网络层(第3层) 1.6 数据链路层&am…

移除链表元素-力扣

一道基础的链表相关题目,在删除时对头节点进行单独处理。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* …

【vue部署】Apache部署vue项目

Apache部署vue项目 Apache 下载安装(windows)1. 下载2. 安装3. 启动服务 vue 部署配置1. 基础配置2. 解决页面刷新问题 Apache 下载安装(windows) 1. 下载 Apache 2.4.59 下载地址:httpd-2.4.59-240404-win64-VS17.zip Visual C Redistributable for Visual Studi…

Go语言通过goroutine实现多协程文件上传

文章推荐 1 作为程序员,开发用过最好用的AI工具有哪些? 2 Github Copilot正版的激活成功,终于可以chat了 3 idea,pycharm等的ai assistant已成功激活 4 新手如何拿捏 Github Copilot AI助手,帮助你提高写代码效率 5 Jetbrains的a…

AWS EC2 连接 AWS RDS(Mysql)

1 创建RDS数据库 点击创建数据库 引擎选项 模板 设置 连接 2 EC2连接Mysql $ sudo yum list mariadb* Installed Packages mariadb-connector-c.x86_64 3.1.13-1.amzn2023.0.3 amazonl…

swig4.2.1压缩包中里面没有找到swig.exe

官网:Simplified Wrapper and Interface Generator C转 C# 采用Swig.exe 打开Example示例的解决方案:sln 生成 即可查看如何调用和使用.i文件 但是:迅雷不管下载哪个版本都是没有exe 官网说了自带。很迷很迷~ 下载其他版本的时候发现&…

TikTok矩阵管理系统:品牌增长的新引擎

随着社交媒体的快速发展,TikTok已成为全球最受欢迎的短视频平台之一。品牌和企业纷纷涌入这个平台,寻求新的增长机会。然而,随着内容的激增和用户群体的多样化,管理TikTok账号变得越来越复杂。这时,TikTok矩阵管理系统…

使用第三方的PyCharm开发工具

目录 PyCharm下载 PyCharm安装 运行PyCharm 创建工程目录 编写“hello world”程序 在同一个工程下创建多个程序文件 运行程序的多种方法 保存程序 关闭程序或工程 删除程序 打开最近的工程 调试断点 熟悉PyCharm开发环境 设置Python解析器 输出彩色控制台文字及…

50道题目!Python、SQL数据库、AB测试、业务分析、机器学习都在这里了!

介绍 每日一题系列已经更新了50道题目啦! 题目难度为初级到中级,涵盖了Python、SQL数据库、AB测试、业务分析、机器学习五大主题,适合初学者和有一定基础的朋友。 原文链接: 50道题目!Python、SQL数据库、AB测试、业务分析、机器…

pycharm 关闭项目卡死

PyCharm2023.3.4 关闭一直卡在 closing projects 解决办法: 打开PyCharm, 选择 Help -> Find Action -> 输入 Registry -> 禁用ide.await.scope.completion

10G SFP双口万兆以太网控制器,高速光口网络接口卡

2-Port 10G SFP NIC 是一款高速网 络接口卡,采用了 PCI Express 3.0 x8 接口,支持双 端口万兆以太网,具有高性能、高可靠性、低功耗等 优点,是数据中心、云计算、虚拟化等领域的理想选 择。 支持多种网络协议,如 …

【加密与解密(第四版)】第十六章笔记

第十六章 脱壳技术 16.1 基础知识 壳的加载过程:保存入口参数、获取壳本身需要使用的API地址、解密原程序各个区块的数据、IAT的初始化、重定位项的处理、HOOK API、跳转到程序原入口点 手动脱壳步骤:查找真正的入口点、抓取内存映像文件、重建PE文件&…

深度学习之基于Pytorch框架新冠肺炎CT图像分类

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 随着新冠肺炎(COVID-19)的全球爆发,快速、准确地诊断疾病成…

MySQL 日志有了解?binlog、redolog、undolog 分别有什么作 用、有什么区别?

MySQL 是一款流行的关系型数据库,其日志是其关键功能之一。MySQL 包括三种类型的日志,分别是binlog、 redolog 和 undolog,它们分别有不同的作用和特点。 binlog ,binlog(Binary log)是 MySQL 中的二进制日志文件,用于…

Python筑基之旅-MySQL数据库(二)

目录 一、第三方库 1、mysql-connector-python 1-1、由来 1-2、优缺点 1-2-1、优点 1-2-1-1、官方支持 1-2-1-2、纯Python实现 1-2-1-3、全面支持 1-2-1-4、兼容性 1-2-1-5、易于使用 1-2-2、缺点 1-2-2-1、性能 1-2-2-2、安装 1-2-2-3、社区支持 1-2-2-4、扩…

Android-虚拟定位

使用虚拟定位软件模拟位置即可 链接: https://pan.baidu.com/s/1JyoGkxB97YyZSDH_yAzKPQ?pwd9cbw 提取码: 9cbw 复制这段内容后打开百度网盘手机App,操作更方便哦

1020. 飞地的数量

1020. 飞地的数量 原题链接:完成情况:解题思路:参考代码:_1020飞地的数量_dfs_定义方向_1020飞地的数量_bfs_定义方向 错误经验吸取 原题链接: 1020. 飞地的数量 https://leetcode.cn/problems/number-of-enclaves/…

十年磨一剑“2024成都电子信息展会”推动电子产业全球发展

2024成都电子展,招商工作已接近尾声,这场盛大的展会不仅是电子信息行业的一次盛会,更是中国西部电子信息产业发展的重要里程碑。自2013年起,中国(西部)电子信息博览会便选择成都作为其永久的举办地&#xf…

windows系统jupyter lab安装和配置:本地开发、探索大模型的利器

前言 在安装好anaconda之后,系统默认就安装好了一个jupyter notebook的工具,该工具可以在网页端运行,类似这样: 提供了一个按行运行的python运行环境,每一步的输出都可以打印到界面,对于我们初学python&am…