Unity中URP下实现深度贴花(雾效支持和BRP适配)

文章目录

  • 前言
  • 一、让我们的贴画支持雾效
    • 1、我们舍弃内部的MixFog方法
    • 2、使用 雾效混合因子 对最后输出颜色进行线性插值相乘
  • 二、在Shader中,限制贴花纹理的采样方式
    • 1、申明 纹理 和 限制采样方式的采样器
    • 2、在片元着色器进行纹理采样
  • 三、BRP适配
    • 1、C#脚本中,打开摄像机深度图
    • 2、适配代码
  • 四、最终代码
    • 1、地缝效果
    • 2、魔法阵
    • 3、芙宁娜贴花


前言

在上一篇文章中,我们实现了贴花的效果。但是,细节效果需要优化。

  • Unity中URP下实现深度贴花

我们在这篇文章中,来优化一下贴花Shader的细节。


一、让我们的贴画支持雾效

  • 原雾效使用方法是只支持不透明对象的。
  • 但是,我们的贴画是半透明的。所以,需要对其进行调整。

1、我们舍弃内部的MixFog方法

col.rgb = MixFog(col.rgb,i.fogCoord);

2、使用 雾效混合因子 对最后输出颜色进行线性插值相乘

  • 这样就可以实现 贴花 融入 雾 的效果
  • 针对Blend One One 的半透明雾效混合

col.rgb*=col.a;
col.rgb *= saturate(lerp(0.5,0,i.fogCoord));


二、在Shader中,限制贴花纹理的采样方式

  • 防止在Unity中,针对单独的纹理设置了不同的重和平铺方式,影响最终效果。

1、申明 纹理 和 限制采样方式的采样器

TEXTURE2D(_MainTex);
#define smp _linear_clamp
SAMPLER(smp);

2、在片元着色器进行纹理采样

half4 mainTex = SAMPLE_TEXTURE2D(_MainTex, smp, uv);


三、BRP适配

1、C#脚本中,打开摄像机深度图

Camera.main.depthTextureMode = DepthTextureMode.Depth;

2、适配代码

	SubShader
    {
        Tags
        {
            //渲染类型
            "RenderType"="Transparent"
            //渲染队列
            "Queue"="Transparent"
        }
        Pass
        {
            Blend One One
            ZWrite Off
            Name "Unlit"

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            // Pragmas
            #pragma target 2.0

            // Includes
            #include "UnityCG.cginc"
            

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _CameraDepthTexture;
            
            struct appdata
            {
                float3 positionOS : POSITION;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float4 positionCS : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 positionOS : TEXCOORD1;
                float3 positionVS : TEXCOORD2;
            };
            
            v2f vert(appdata v)
            {
                v2f o;
                o.positionCS = UnityObjectToClipPos(v.positionOS);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.positionOS = v.positionOS;
                //2、通过模型面片的求出像素在观察空间下的坐标值
                o.positionVS = UnityWorldToViewPos(mul(unity_ObjectToWorld,o.positionOS));
                
                return o;
            }
            
            half4 frag(v2f i) : SV_TARGET
            {
                //思路:
                float4 depthVS = 1;
                //1、通过深度图求出像素所在视图空间的Z值
                float2 screenUV = i.positionCS.xy / _ScreenParams.xy;
                half4 depthTex = tex2D(_CameraDepthTexture, screenUV);
                half depthZ = LinearEyeDepth(depthTex.r);

                //2、通过模型面片的求出像素在观察空间下的坐标值
                //这个在顶点着色器中完成

                //3、结合两者求出 深度图中像素的 XYZ值
                depthVS.z = depthZ;
                depthVS.xy = i.positionVS.xy * depthZ / -i.positionVS.z;
                //4、再将此坐标转换到模型的本地空间,把XY作为UV来进行纹理采样
                float4 depthWS = mul(unity_CameraToWorld, depthVS);
                float4 depthOS = mul(unity_WorldToObject, depthWS);
                float2 uv = depthOS.xz+0.5;

                half4 col = 0;
                half4 mainTex = tex2D(_MainTex,uv);
                col += mainTex;
                //针对Blend One One 的半透明雾效混合
                col.rgb*=col.a;
                
                return col;
            }
            ENDCG
        }
    }

四、最终代码

1、地缝效果

请添加图片描述

2、魔法阵

请添加图片描述

3、芙宁娜贴花

请添加图片描述

//深度贴花
Shader "MyShader/URP/P4_4_2"
{
    Properties
    {
        [Header(MainTex)]
        _MainTex("MainTex",2D) = "white"{}

    }
    SubShader
    {
        Tags
        {
            //告诉引擎,该Shader只用于 URP 渲染管线
            "RenderPipeline"="UniversalPipeline"
            //渲染类型
            "RenderType"="Transparent"
            //渲染队列
            "Queue"="Transparent"
        }

        Pass
        {
            Blend One One
            ZWrite Off
            Name "Unlit"

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            // Pragmas
            #pragma target 2.0

            // Includes
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"

            CBUFFER_START(UnityPerMaterial)
                float4 _MainTex_ST;
            CBUFFER_END

            TEXTURE2D(_CameraDepthTexture);
            SAMPLER(sampler_CameraDepthTexture);
            TEXTURE2D(_MainTex);
            //SAMPLER(sampler_MainTex);
            #define smp _linear_clamp
            SAMPLER(smp);
            //struct appdata
            //顶点着色器的输入
            struct Attributes
            {
                float3 positionOS : POSITION;
                float2 uv : TEXCOORD0;
            };

            //struct v2f
            //片元着色器的输入
            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float2 uv : TEXCOORD0;
                float fogCoord : TEXCOORD1;
                float3 positionOS : TEXCOORD2;
                float3 positionVS : TEXCOORD3;
            };

            //v2f vert(Attributes v)
            //顶点着色器
            Varyings vert(Attributes v)
            {
                Varyings o;
                o.positionCS = TransformObjectToHClip(v.positionOS);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.fogCoord = ComputeFogFactor(o.positionCS.z);
                o.positionOS = v.positionOS;
                //2、通过模型面片的求出像素在观察空间下的坐标值
                o.positionVS = TransformWorldToView(TransformObjectToWorld(o.positionOS));
                return o;
            }

            //fixed4 frag(v2f i) : SV_TARGET
            //片元着色器
            half4 frag(Varyings i) : SV_TARGET
            {
                //思路:
                float4 depthVS = 1;
                //1、通过深度图求出像素所在视图空间的Z值
                float2 screenUV = i.positionCS.xy / _ScreenParams.xy;
                half4 depthTex = SAMPLE_TEXTURE2D(_CameraDepthTexture, sampler_CameraDepthTexture, screenUV);
                half depthZ = LinearEyeDepth(depthTex.r, _ZBufferParams);

                //2、通过模型面片的求出像素在观察空间下的坐标值
                //这个在顶点着色器中完成

                //3、结合两者求出 深度图中像素的 XYZ值
                depthVS.z = depthZ;
                depthVS.xy = i.positionVS.xy * depthZ / -i.positionVS.z;
                //4、再将此坐标转换到模型的本地空间,把XY作为UV来进行纹理采样
                float4 depthWS = mul(unity_CameraToWorld, depthVS);
                float4 depthOS = mul(unity_WorldToObject, depthWS);
                float2 uv = depthOS.xz + 0.5;

                half4 col = 0;
                half4 mainTex = SAMPLE_TEXTURE2D(_MainTex, smp, uv);
                col += mainTex;
                //针对Blend One One 的半透明雾效混合
                col.rgb *= col.a;
                col.rgb *= saturate(lerp(1, 0, i.fogCoord));
                //col.rgb = MixFog(col.rgb,i.fogCoord);
                return col;
            }
            ENDHLSL
        }
    }
    SubShader
    {
        Tags
        {
            //渲染类型
            "RenderType"="Transparent"
            //渲染队列
            "Queue"="Transparent"
        }
        Pass
        {
            Blend One One
            ZWrite Off
            Name "Unlit"

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            // Pragmas
            #pragma target 2.0

            // Includes
            #include "UnityCG.cginc"


            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _CameraDepthTexture;

            struct appdata
            {
                float3 positionOS : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 positionCS : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 positionOS : TEXCOORD1;
                float3 positionVS : TEXCOORD2;
            };

            v2f vert(appdata v)
            {
                v2f o;
                o.positionCS = UnityObjectToClipPos(v.positionOS);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.positionOS = v.positionOS;
                //2、通过模型面片的求出像素在观察空间下的坐标值
                o.positionVS = UnityWorldToViewPos(mul(unity_ObjectToWorld, o.positionOS));

                return o;
            }

            half4 frag(v2f i) : SV_TARGET
            {
                //思路:
                float4 depthVS = 1;
                //1、通过深度图求出像素所在视图空间的Z值
                float2 screenUV = i.positionCS.xy / _ScreenParams.xy;
                half4 depthTex = tex2D(_CameraDepthTexture, screenUV);
                half depthZ = LinearEyeDepth(depthTex.r);

                //2、通过模型面片的求出像素在观察空间下的坐标值
                //这个在顶点着色器中完成

                //3、结合两者求出 深度图中像素的 XYZ值
                depthVS.z = depthZ;
                depthVS.xy = i.positionVS.xy * depthZ / -i.positionVS.z;
                //4、再将此坐标转换到模型的本地空间,把XY作为UV来进行纹理采样
                float4 depthWS = mul(unity_CameraToWorld, depthVS);
                float4 depthOS = mul(unity_WorldToObject, depthWS);
                float2 uv = depthOS.xz + 0.5;

                half4 col = 0;
                half4 mainTex = tex2D(_MainTex, uv);
                col += mainTex;
                //针对Blend One One 的半透明雾效混合
                col.rgb *= col.a;

                return col;
            }
            ENDCG
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法——贪心法(Greedy)

贪心法 把整个问题分解成多个步骤,在每个步骤都选取当前步骤的最优方案,直到所有步骤结束;在每一步都不考虑对后续步骤的影响,在后续步骤中也不再回头改变前面的选择。不足之处: 贪心算法并不能保证获得全局最优解&…

用通俗易懂的方式讲解:内容讲解+代码案例,轻松掌握大模型应用框架 LangChain

本文介绍了 LangChain 框架,它能够将大型语言模型与其他计算或知识来源相结合,从而实现功能更加强大的应用。 接着,对LangChain的关键概念进行了详细说明,并基于该框架进行了一些案例尝试,旨在帮助读者更轻松地理解 L…

申请ZeroSSL泛域名域名证书 并部署阿里云测试

安装acme.sh 安装过程中可能会失败 多试几次就会成功 wget -O - https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online -m 你的邮箱gmail.com安装完成后重新加载 Bash: source ~/.bashrc然后也可以开启自动更…

若依基于sm-crypto实现前后端登录密码加密

上一节介绍了基于jsencrypt实现的密码加密解密登录功能,这次来介绍基于sm-crypto实现前后端登录密码加密,本次采用的是sm2进行的加密解密。 后端 首先从后端代码开始写起(因为公钥和私钥都是要从java代码中生成): 首先需要引入sm-crypto的j…

ubantu运维,nginx相关操作

1、使用 命令ps aux | grep nginx查找nginx 运行目录,如下图: 2、使用 ​​​​​​​命令cd /usr/sbin 切换到nginx 运行目录,如下图: 3、修改配置文件后,使用 nginx -t 命令测试nginx配置文件的语法是否正确&#x…

RTMP 视频数据封装

RTMP 协议 与HTTP(超文本传输协议)同样是一个基于TCP的Real Time Messaging Protocol(实时消息传输协议)。由Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的一种开放协议 。在国内被广泛的应用于直 播领域。HTTP默认端口为80,RTMP则为1935…

Python 安卓开发:Kivy、BeeWare、Flet、Flutter

kivy:https://github.com/kivy python-for-android :https://python-for-android.readthedocs.io/en/latest/ BeeWare:https://docs.beeware.org/en/latest/ Flet:https://github.com/flet-dev/flet 把 PySide6 移植到安卓上去&a…

如何使用网络测试仪构造特殊流量

为什么要仿真特殊流量 在现网中,网络流量时常伴随着突发,突发流量可能会造成网络的拥塞,从而产生丢包、抖动和时延,导致网络服务质量整体下降。面对宏观上的突发,通常采用在网络设备入向限速或者流量整形功能来消除突…

kotlin运行

1.使用android studio 由于我本身是做android的,android studio本身有内置kotlin的插件。但若只是想跑kotlin的程序,并不像和android程序绑在一起,可以创建一个kt文件,在里面写一个main函数,就可以直接运行kotlin程序…

MySQL第二次

作业要求: 作业代码实现: create database db_04 default charsetutf8mb4;use db_04;create table if not exists t_hero(id int primary key auto_increment,name varchar(20) not null unique,nickname varchar(50) not null unique,address varchar…

Vue面试之v-if与v-show的区别

Vue面试之v-if与v-show的区别 DOM渲染初始渲染性能切换开销标签配合源码实现 最近在整理一些前端面试中经常被问到的问题,分为vue相关、react相关、js相关、react相关等等专题,可持续关注后续内容,会不断进行整理~ 作为Vue中两种条件性渲染元…

Python 最新版本 3.12.1 环境配置(windows)

文章目录 python 3.12.1环境安装3.12.1 网盘下载3.12.1 官网下载 python 安装完成测试第一个 python 程序Hello Python python 3.12.1环境安装 3.12.1 网盘下载 python 3.12.1 百度网盘地址:https://pan.baidu.com/s/1SAcH_uH0T3DiERn6AZeQlg?pwd4242 提取码&a…

跟着cherno手搓游戏引擎【4】窗口抽象、GLFW配置、窗口事件

引入GLFW: 在vendor里创建GLFW文件夹: 在github上下载,把包下载到GLFW包下。 GitHub - TheCherno/glfw: A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input修改SRC/premake5.lua的配置:12、13、15、36…

阿里云服务器ECS介绍_高性能云服务器_为了无法计算的价值

阿里云高性能云服务器60%单实例最大性能提升,35Gbps内网带宽,网络增强&通用型云服务器、本地SSD型云服务器、大数据型云服务器、GPU异构型云服务器,阿里云百科aliyunbaike.com分享阿里云高性能云服务器: 阿里云高性能云服务器…

修改权限控制(chmod命令、chown命令)

1.chmod命令 功能:修改文件、文件夹权限(注意,只有文件、文件夹的所属用户或root用户可以修改) 语法:chmod [-R] 权限 参数 权限,要设置的权限,比如755,表示:rwxr-xr-x…

Python入门-面向对象

1.类和对象 是不是很熟悉?和Java一样,在Python中,都可以把万物看成(封装成)对象。它俩都是面向对象编程 1.1 查看对象数据类型 a 10 b 9.8 c helloprint(type(a)) print(type(b)) print(type(c))运行结果: D:\Python_Home\v…

自定义数据实现SA3D

SA3D:Segment Anything in 3D with NeRFs 实现了3D目标分割 原理是利用SAM(segment anything) 模型和Nerf分割渲染3D目标, SAM只能分块,是没有语义标签的,如何做到语义连续? SA3D中用了self-prompt, 根据前一帧的mask…

基于Python的汽车信息爬取与可视化分析系统

介绍 这款汽车信息网站是基于多项技术和框架设计的全面的汽车信息展示及查询系统。其中,采用了Python Django框架和Scrapy爬虫技术实现数据的抓取和处理,结合MySQL数据库进行数据存储和管理,利用Vue3、Element-Plus、ECharts以及Pinia等前端…

MFC为资源对话框添加消息处理函数和初始化控件

现在我VC6新建了一个对话框工程;又在资源添加了一个新的对话框,并为新的对话框添加了名为CTestDlg的类; 在主对话框的cpp文件包含#include "TestDlg.h"; 在主对话框的cpp文件的OnInitDialog()成员函数中,添…

leetcode 2645. 构造有效字符串的最少插入数-python

题目: 给你一个字符串 word ,你可以向其中任何位置插入 “a”、“b” 或 “c” 任意次,返回使 word 有效 需要插入的最少字母数。 如果字符串可以由 “abc” 串联多次得到,则认为该字符串 有效 。 解题方法 1.先判断字符串是否…