文章目录
- 前言
- 一、交接处高亮 原理
- 1、 我们先用一个球作为能量罩、一个Cube 和 一个 椭球 作为与能量罩交接的物体
- 2、 这是我们目前场景的深度图
- 3、使能量罩为 半透明渲染队列 且 关闭深度写入 不渲染深度图
- 二、交接处高亮 实现
- 1、得到深度图
- 2、在片元着色器中,对深度图进行纹理采样
- 3、得到深度图 观察空间下的Z值
- 4、得到 深度图 观察空间Z值 和 能量罩观察空间Z值 的 差值
- 5、用1 - depth得到反色
- 6、在属性面板定义一个参数用于控制高亮范围
- 6、在属性面板定义一个Color用于控制高亮颜色
- 请添加图片描述
- 三、测试代码
前言
在之前的文章中,我们实现了 深度图 和 抓屏 的使用。我们用这些功能来实现一下能量罩效果。
-
Unity中URP下使用屏幕坐标采样深度图
-
Unity中URP下抓屏的 开启 和 使用
一、交接处高亮 原理
1、 我们先用一个球作为能量罩、一个Cube 和 一个 椭球 作为与能量罩交接的物体
2、 这是我们目前场景的深度图
- 我们要实现交接处高亮,使用交接外面的部分,是实现不了的
- 因为,用深度图观察空间下的Z值 和 物体能量罩的观察空间Z轴,得到外面的部分 和 之前的是一致的
- 所以,我们得用 深度图 和 能量罩的观察空间Z轴,来得到 交接处内部区域高亮
3、使能量罩为 半透明渲染队列 且 关闭深度写入 不渲染深度图
- 这样能量罩就不被深度图渲染了
- 我们就可以使用 深度图观察空间下的Z值 和 能量罩的观察空间Z值 得到 交接的内部区域了
二、交接处高亮 实现
1、得到深度图
- 申明 深度图 纹理 和 深度图采样器
TEXTURE2D(_CameraDepthTexture);SAMPLER(sampler_CameraDepthTexture);
2、在片元着色器中,对深度图进行纹理采样
float2 uv = i.positionCS.xy/ _ScreenParams.xy;
float4 cameraDepthTex = SAMPLE_TEXTURE2D(_CameraDepthTexture,sampler_CameraDepthTexture,uv);
3、得到深度图 观察空间下的Z值
float depthTex = LinearEyeDepth(cameraDepthTex,_ZBufferParams);
4、得到 深度图 观察空间Z值 和 能量罩观察空间Z值 的 差值
- 由于观察空间是右手坐标系。所以该Z值是负值。
- 能量罩观察空间Z值,需要在顶点着色器中提前计算好,从顶点着色器传入片元着色器
- 差值 = 用深度图观察空间Z值 + 能量罩观察空间Z值
float4 depth = depthTex + i.positionVS.z;
5、用1 - depth得到反色
float4 highLight = 1 - depth;
6、在属性面板定义一个参数用于控制高亮范围
- 相乘节省性能
highLight *= _HighLightFade;
- 指数效果更佳
highLight = pow(highLight,_HighLightFade);
6、在属性面板定义一个Color用于控制高亮颜色
highLight *= _HighLightColor;
三、测试代码
Shader "MyShader/URP/P4_3"
{
Properties
{
_HighLightColor("HighLightColor",Color) = (0,0,0,0)
_HighLightFade("HighLight",Float) = 1.0
}
SubShader
{
Tags
{
//告诉引擎,该Shader只用于 URP 渲染管线
"RenderPipeline"="UniversalPipeline"
//渲染类型
"RenderType"="Transparent"
//渲染队列
"Queue"="Transparent"
}
//Blend One One
ZWrite Off
Pass
{
Name "Unlit"
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
// 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)
half4 _HighLightColor;
half _HighLightFade;
CBUFFER_END
TEXTURE2D(_CameraDepthTexture);SAMPLER(sampler_CameraDepthTexture);
//struct appdata
//顶点着色器的输入
struct Attributes
{
float3 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
//struct v2f
//片元着色器的输入
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float4 screenPos : TEXCOORD1;
float3 positionVS : TEXCOORD2;
};
//v2f vert(Attributes v)
//顶点着色器
Varyings vert(Attributes v)
{
Varyings o = (Varyings)0;
float3 positionWS = TransformObjectToWorld(v.positionOS);
o.positionVS = TransformWorldToView(positionWS);
o.positionCS = TransformWViewToHClip(o.positionVS);
o.screenPos = ComputeScreenPos(o.positionCS);
return o;
}
//fixed4 frag(v2f i) : SV_TARGET
//片元着色器
half4 frag(Varyings i) : SV_TARGET
{
//深度图
//float2 uv = i.screenPos.xy / i.screenPos.w;
float2 uv = i.positionCS.xy/ _ScreenParams.xy;
float4 cameraDepthTex = SAMPLE_TEXTURE2D(_CameraDepthTexture,sampler_CameraDepthTexture,uv);
float depthTex = LinearEyeDepth(cameraDepthTex,_ZBufferParams);
float depth = depthTex + i.positionVS.z;
float4 highLight = 1 - depth;
highLight = pow(highLight,_HighLightFade);
highLight *= _HighLightColor;
return highLight;
}
ENDHLSL
}
}
}