透明物体的投射和接收阴影

news2024/11/25 13:43:49

1、让透明度测试Shader投射阴影

(1)同样我们使用FallBack的形式投射阴影,但是需要注意的是,FallBack的内容为:Transparent / Cutout / VertexLit,该默认Shader中会把裁剪后的物体深度信息写入到 阴影映射纹理和摄像机深度图中
注意:使用该默认Shader计算投射阴影时,需要使用_Cutwoff属性 和 _Color属性来进行相关计算,因此我们必须保证我们的Shader当中有名为_Cutoff的阈值属性 和 _Color的漫反射颜色属性,否则无法得到正确阴影结果

(2)为了得到正确的阴影效果,我们需要将该物体的Cast Shadows(投射阴影)属性设置为Two Sided(双面),强制让Unity计算阴影隐射纹理时计算所有面的深度信息。因为如果不设置,默认将物体渲染到阴影隐射纹理和摄像机深度图时只会考虑物体的正面,背对光源的面不会参与计算(左图),设置为双面后即可参与计算,得到正确的结果(右图)。

3、让透明度测试Shader接收阴影

主要分5步骤:
(1)编译指令:#pragma multi_compile_fwdbase
用于帮助我们编译所有变体 并且保证衰减相关光照变量能够正确赋值到对应的内置变量中
(2)包含内置文件: #include "AutoLight.cginc"
(3)结构体中声明阴影坐标宏:SHADOW_COORDS(n)
n为下一个可用的插值寄存器的索引值(结构体前面有几个TEXCOORD就填几)
(4)坐标转换宏:TRANSFER_SHADOW(o);
(5)Unity光照衰减计算宏:UNITY_LIGHT_ATTENUATION(atten, v2f结构体, 顶点世界坐标位置);

Shader "ShaderProj/4/TranparentTest_Both"
{
    Properties
    {
        _MainTex("MainTex", 2D) = ""{}
        _Color("MainColor", Color) = (1,1,1,1)
        _SpecularColor("SpecularColor", Color) = (1,1,1,1)
        _SpecularNum("SpecularNum", Range(0,20)) = 15
        _Cutoff("CutOff", Range(0,1)) = 0       // 透明度测试阈值
    }
    SubShader
    {
        Tags{
            "Queue"="AlphaTest"
            "IgnoreProjector"="True"
            "RenderType"="TransparentCutout"
            }

        Pass
        {
            Tags { "LightMode"="ForwardBase" }

            // 关闭剔除,正面背面都被渲染
            Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwdbase
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Color;
            fixed4 _SpecularColor;
            float _SpecularNum;
            fixed _Cutoff;

            struct v2f
            {
                float4 pos:SV_POSITION;
                float2 uv:TEXCOORD0;
                float3 wNormal:NORMAL;
                float3 wPos:TEXCOORD01;
                SHADOW_COORDS(2)
            };

            fixed3 getLambertColor(float3 normal, float3 lightDir, fixed3 albedo)
            {
                fixed3 color = _LightColor0 * albedo * max(0, dot(lightDir, normal));

                return color;
            }

            fixed3 getSpecularColor(float3 worldPos, float3 normal, float3 lightDir)
            {
                //float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos);
                float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
                float3 halfAngle = normalize(viewDir + lightDir);
                fixed3 color = _LightColor0 * _SpecularColor * pow(max(0, dot(normal, halfAngle)), _SpecularNum);

                return color;
            }
        
            v2f vert (appdata_base v)
            {
                v2f data;

                data.pos = UnityObjectToClipPos(v.vertex);
                data.wNormal = UnityObjectToWorldNormal(v.normal);
                data.wPos = mul(unity_ObjectToWorld, v.vertex);
                data.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                //data.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;

                TRANSFER_SHADOW(data)

                return data;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // 透明度测试
                fixed4 texColor = tex2D(_MainTex, i.uv);
                clip(texColor.a - _Cutoff);

                //计算光照衰减和阴影衰减的宏
                UNITY_LIGHT_ATTENUATION(atten, i, i.wPos)

                fixed3 albedo = texColor.rgb * _Color.rgb;                
                float3 lightDir = normalize(_WorldSpaceLightPos0);
                fixed3 lambertColor = getLambertColor(i.wNormal, lightDir, albedo);
                fixed3 specularColor = getSpecularColor(i.wPos, i.wNormal, lightDir);
                fixed3 color = (lambertColor + specularColor) * atten + UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;

                return fixed4(color, 1);
            }
            ENDCG
        }
    }
    Fallback "Transparent/Cutout/VertexLit"
}

3、透明度混合处理阴影

根据透明度测试的思路,我们如果想要物体产生阴影效果无非就两步:
(1)投射阴影
    在FallBack中关联内置的对应Shader("Transparent/VertexLit")
(2)接受阴影
    在Shader中书写计算阴影衰减值的相关代码
因此对于透明度混合的Shader也会使用同样的思路去制作

但是!!!由于透明度混合需要关闭深度写入,而阴影相关的处理需要用到深度值参与计算,因此Unity中从性能方面考虑(要计算半透明物体的的阴影表现效果是相对复杂的),所有的内置半透明Shader都不会产生阴影效果(比如 Transparent/ VertexLit)
因此
2 - 1.透明混合Shader想要 投射阴影时
不管你在FallBack中写入哪种自带的半透明混合Shader,都不会有投射阴影的效果,因为深度不会写入

2 - 2.透明混合Shader想要 接受阴影时
Unity内置关于阴影接收计算的相关宏,不会计算处理透明混合Shader【混合因子 设置为半透明效果(Blend SrcAlpha OneMinusSrcAlpha)的Shader】
因为透明混合物体的深度值和遮挡关系无法直接用传统的深度缓冲和阴影贴图来处理

结论:Unity中不会直接为透明度混合Shader处理阴影

4、透明度混合强制生成阴影

在FallBack中设置一个非透明Shader,比如VertexLit、Diffuse等,用其中的灯光模式设置为阴影投射的渲染通道来参与阴影映射纹理的计算,把该物体当成一个实体物体处理,但是,这种效果并不真实,不建议使用

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

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

相关文章

降重秘籍:如何利用ChatGPT将重复率从45%降至10%以下?

AIPaperGPT,论文写作神器~ https://www.aipapergpt.com/ 重复率高达45%?很多人一查论文的重复率,瞬间想“完了,这次真的要重写了”。但其实不用这么绝望!有了ChatGPT,降重真的没那么难。今天就教你几招&a…

VGG16模型实现MNIST图像分类

MNIST图像数据集 MNIST(Modified National Institute of Standards and Technology)是一个经典的机器学习数据集,常用于训练和测试图像处理和机器学习算法,特别是在数字识别领域。该数据集包含了大约 7 万张手写数字图片&#xf…

wsl环境下安装MySQL5.7

安装操作需root权限: 1-通过 sudo su - ,切换到root用户。 2-在每一个命令前加上sudo,临时提升权限 1、下载apt仓库文件 wget https://dev.mysql.com/get/mysql-apt-config_0.8.12-1_all.deb 安装包是.deb的文件2、配置仓库,使…

MyBatis 批量插入方案

MyBatis 批量插入 MyBatis 插入数据的方法有几种: for 循环,每次都重新连接一次数据库,每次只插入一条数据。 在编写 sql 时用 for each 标签,建立一次数据库连接。 使用 MyBatis 的 batchInsert 方法。 下面是方法 1 和 2 的…

Linux防火墙-案例(一)filter表

作者介绍:简历上没有一个精通的运维工程师。希望大家多多关注作者,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们经过上小章节讲了Linux的部分进阶命令,我们接下来一章节来讲讲Linux防火墙。由于目前以云服务器为主&#x…

51单片机的水位检测系统【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块水位传感器继电器LED、按键和蜂鸣器等模块构成。适用于水位监测、水位控制、水位检测相似项目。 可实现功能: 1、LCD1602实时显示水位高度 2、水位传感器采集水位高度 3、按键可设置水位的下限 4、按键可手动加…

动手学大模型应用开发之大模型简介

动手学大模型应用开发之大模型简介 主要学习目标什么是大语言模型大模型的能力和特点涌现能力作为基座模型支持多元应用的能力支持对话作为统一入口的能力大模型特点 常见大模型ChatGpt通义千问 LangChainLangChain的核心模块 总结相关学习链接 主要学习目标 学习如何进行大模…

【AI知识点】激活函数(Activation Function)

激活函数(Activation Function) 是神经网络中的一个关键组件,负责将输入的线性组合转化为非线性输出。它赋予神经网络模型以复杂的表达能力,使其能够处理非线性问题,比如分类、图像识别和自然语言处理等任务。 1. 激活…

【redis-06】redis的stream流实现消息中间件

redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325【二】redis的持久化机制和原理https://zhenghuisheng.blog.csdn.net/article/details/142441756【三】redis缓存穿透、缓存击穿、缓存雪崩htt…

Spring Boot:医院管理的数字化转型

5系统详细实现 5.1 医生模块的实现 5.1.1 病床信息管理 医院管理系统的医生可以管理病床信息,可以对病床信息添加修改删除操作。具体界面的展示如图5.1所示。 图5.1 病床信息管理界面 5.1.2 药房信息管理 医生可以对药房信息进行添加,修改,…

今日指数day8实战补充用户管理模块(下)

ps : 由于前端将userId封装为BigInt类型 , 导致有精度损失, 传入的userId不正确 , 部分功能无法正确实现 , 但是代码已经完善 1.4 更新用户角色信息接口说明 1)原型效果 2)接口说明 功能描述:更新用户角色信息 服务路径:/user/…

基于FPGA的ov5640摄像头图像采集(二)

之前讲过ov5640摄像头图像采集,但是只包了的摄像头驱动与数据对齐两部分,但是由于摄像头输入的像素时钟与HDMI输出的驱动时钟并不相同,所有需要利用DDR3来将像素数据进行缓存再将像素数据从DDR3中读出,对DDR3的读写参考米联客的IP…

别再为日期时间头疼了!Python datetime模块助你高效搞定一切时间问题,让你的代码从此与时间赛跑,快人一步!

博客主页:长风清留扬-CSDN博客系列专栏:Python基础专栏每天更新大数据相关方面的技术,分享自己的实战工作经验和学习总结,尽量帮助大家解决更多问题和学习更多新知识,欢迎评论区分享自己的看法感谢大家点赞&#x1f44…

花半小时用豆包Marscode 和 Supabase免费部署了一个远程工作的导航站

以下是「 豆包MarsCode 体验官」优秀文章,作者谦哥。 🚀 项目地址:remotejobs.justidea.cn/ 🚀 项目截图: 数据处理 感谢开源项目:https://github.com/remoteintech/remote-jobs 网站信息获取&#xff1…

MyBatis 操作数据库入门

目录 前言 1.创建springboot⼯程 2.数据准备 3.配置Mybatis数据库连接信息 4.编写SQL语句,进行测试 前言 什么是MyBatis? MyBatis是⼀款优秀的 持久层 框架,⽤于简化JDBC的开发 Mybatis操作数据库的入门步骤: 1.创建springboot⼯程 2.数…

SOMEIP_ETS_171: SD_Unicast_FindService

测试目的: 验证DUT能够响应Tester发送的多个单播FindService消息,并至少回复一个单播OfferService消息。 描述 本测试用例旨在确保DUT能够正确处理单播FindService消息请求,并为请求的服务提供至少一个单播OfferService消息作为响应。 测…

SpringBootWeb快速入门!详解如何创建一个简单的SpringBoot项目?

在现代Web开发中,SpringBoot以其简化的配置和快速的开发效率而受到广大开发者的青睐。本篇文章将带领你从零开始,搭建一个基于SpringBoot的简单Web应用~ 一、前提准备 想要创建一个SpringBoot项目,需要做如下准备: idea集成开发…

亲身经历告诉你该如何自学编程

我2016年硕士毕业后,从一个纯机械学生开始转行做软件开发,其中少不了要自学编程,这其中经历的到现在看来还历历在目。 我曾经写过一些关于我转行做软件开发经历的文章,如果你感兴趣,可以点击这里的链接(我…

国庆期间的问题,如何在老家访问杭州办公室的网络呢

背景:国庆期间的问题,如何在老家访问杭州办公室的网络呢 实现方案:异地组网 实现语言:Java 环境:三个网络,一台拥有公网IP的服务器、一台杭州本地机房内服务器、你老家所在网络中的一台电脑(…

【Git】TortoiseGitPlink提示输入密码解决方法

问题 克隆仓库,TortoiseGitPlink提示输入密码 解法 1、打开TortoiseGit 下的puttygen工具 位置:C:\Program Files\TortoiseGit\bin\ 2、点击【Load】按钮,载入 C:\Users\Administrator\.ssh\ 文件夹下的id_rsa文件。 3、点击save private …