Unity 渲染教程(十二):半透明材质的阴影

这篇博客介绍了在Unity中处理半透明材质阴影的方法,包括剪切造成的阴影、实心阴影的区别,以及如何重构阴影着色器以支持透明度。通过调整着色器代码,实现了在剪切渲染模式下对片段进行裁剪,以及在半透明渲染模式下使用抖动技术创建部分阴影。最后,博客讨论了Unity中半透明阴影的局限性和如何在UI中添加开关以选择不同的阴影处理方式。
摘要由CSDN通过智能技术生成

剪切造成的阴影

目前,我们透明材质的阴影总是像是由不透明材质投射的一样,因为这是我们的着色器所假设的一个条件。因此,阴影可能会显得很奇怪,直到你意识到你看到的是一个不透明对象所投射的阴影。在方向光生成的阴影情况下,这也可以导致不可见的几何体遮挡阴影。

在不透明渲染模式和剪切渲染模式下,所得到的方向阴影是相同的。

在聚光灯或点光源生成光影的情况下,你会得到一个实心的阴影。

实心的聚光灯阴影。

重构我的阴影

为了把透明度考虑进来,我们必须访问阴影投射着色器渲染通道中的透明度值。这意味着我们需要对反射率纹理进行采样。但是,当使用不透明渲染模式的时候,我们不需要对反射率纹理进行采样。所以我们需要为我们的阴影使用多个着色器变体。

现在我们有两个版本的阴影程序。 一个版本用于立方体阴影贴图,这是点光源所需的,一个用于其他光源类型。现在我们需要混合更多的变体。为了使混合更多的变体更容易,我们将重写My Shadow这个导入文件。我们将为所有变体使用插值器,并创建单个顶点和片段程序。

首先,将Interpolator的定义移出条件块。然后使光向量成为条件。

structVertexData {

float4 position : POSITION;

float3 normal : NORMAL;

};

structInterpolators {

float4 position : SV_POSITION;

#if defined(SHADOWS_CUBE)

float3 lightVec : TEXCOORD0;

#endif

};

接下来,写一个新的顶点程序,其中包含两个不同版本的副本。非立方体的代码必须稍微调整以使用新的Interpolator输出。

Interpolators MyShadowVertexProgram (VertexData v) {

Interpolators i;

#if defined(SHADOWS_CUBE)

i.position = UnityObjectToClipPos(v.position);

i.lightVec =

mul(unity_ObjectToWorld, v.position).xyz - _LightPositionRange.xyz;

#else

i.position = UnityClipSpaceShadowCasterPos(v.position.xyz, v.normal);

i.position = UnityApplyLinearShadowBias(i.position);

#endif

returni;

}

对片段程序执行相同操作。然后摆脱旧的条件程序

float4 MyShadowFragmentProgram (Interpolators i) : SV_TARGET {

#if defined(SHADOWS_CUBE)

floatdepth = length(i.lightVec) + unity_LightShadowBias.x;

depth *= _LightPositionRange.w;

returnUnityEncodeCubeShadowDepth(depth);

#else

return0;

#endif

}

//#if defined(SHADOWS_CUBE)

//            …

//#endif

裁剪阴影片段

我们首先处理剪切造成的阴影。 我们通过丢弃片段在阴影中切孔,就像我们在剪切渲染模式中的其他渲染过程中所做的那样。为达到这个目的,我们需要材料的色调、反射率纹理和透明度截止阈值这些信息。在My Shadows的顶部为它们添加相应的变量。

#include "UnityCG.cginc"

float4 _Tint;

sampler2D _MainTex;

float4 _MainTex_ST;

float_AlphaCutoff;

因此,当我们使用剪切渲染模式的时候,我们必须对反射率纹理进行采样。实际上,当我们不使用反射率纹理的透明度值来确定平滑度的时候我们必须这样做。当满足这些条件的时候,我们必须将UV坐标传递给片段程序。 同时如果满足这些条件的话,我们将SHADOWS_NEED_UV定义为1。这样,我们可以方便地使用#if SHADOWS_NEED_UV

#include "UnityCG.cginc"

#if defined(_RENDERING_CUTOUT) && !defined(_SMOOTHNESS_ALBEDO)

#define SHADOWS_NEED_UV 1

#endif

将UV坐标添加到顶点输入数据。我们不需要让顶点输入数据成为有条件的。然后有条件地将UV坐标添加到内插值器里面去。</

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农老K

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值