Unity中的半透明阴影

摘要:
Unity提供的抖动纹理可用于渲染Unity中的半透明阴影。在此之前,请考虑一般半透明对象的渲染过程:将渲染队列设置为“透明”,以便首先渲染不透明对象,然后无需渲染被不透明对象遮挡的透明对象。减少开销并将渲染类型设置为“透明”,这便于某些替换操作设置混合模式。例如,fade为srcBlend=SrcAlpha,dstBlend=OneMinusSrcAlph,Transparent为src混纺=One,dstBlend=OneMineusSrcArpha关闭深度写入。zwrite=false Unity中的半透明阴影本质上是不透明的,仅对抖动纹理进行采样。根据采样结果,单击以删除一些片段,这样阴影投射过程中的部分阴影信息将仅绘制在阴影贴图上。

在Unity中渲染半透明阴影可以使用Unity提供的dither texture。在这之前,先考虑一般半透明物体的渲染流程:

  • 设置render queue为Transparent,这样不透明的物体会先渲染,然后位于被不透明物体遮挡的透明物体就可以不必渲染,减少开销
  • 设置render type为Transparent,便于一些replacement操作
  • 设置blend mode,例如fade是srcBlend = SrcAlpha,dstBlend = OneMinusSrcAlpha,而Transparent是srcBlend = One,dstBlend = OneMinusSrcAlpha
  • 关闭深度写入,zwrite = false

Unity中的半透明阴影本质上是不透明的,只是对dither texture进行采样,根据采样的结果,clip掉一些fragment,使得shadow caster过程中只有一部分阴影信息会被绘制到shadowmap上。Unity builtin shaders提供的参考写法如下:

struct Interpolators {
	UNITY_VPOS_TYPE vpos : VPOS;
    ...
};

float4 MyShadowFragmentProgram (Interpolators i) : SV_TARGET {
    ...
	half alphaRef = tex3D(_DitherMaskLOD, float3(vpos.xy*0.25,alpha*0.9375)).a;
    clip(dither - 0.01);
    ...
}

vpos表示的是当前像素在screen space下的坐标,_DitherMaskLOD是一个尺寸为4×4×16的3D纹理,这个可以从frame debug中看出:

Unity中的半透明阴影第1张

这个纹理长啥样呢?我们可以写一个shader手动把它输出:

Shader "Custom/TextureViewShader"
{
    Properties
    {
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            sampler3D _DitherMaskLOD;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                i.uv *= 16;
                fixed4 col = tex3D(_DitherMaskLOD, float3(i.uv, floor(i.uv.x) * 0.0625)).a;
                return col;
            }
            ENDCG
        }
    }
}

从frame debug可知纹理是alpha8格式,因而只需输出alpha通道值:

Unity中的半透明阴影第2张

由于_DitherMaskLOD纹理是4×4×16的,我们实际上在v方向也重复了16次,因此真正的纹理长这样:

Unity中的半透明阴影第3张

可以看出,该纹理从4×4的全黑像素开始,随着维度z的增加,黑色像素每次减少1个,直至最后全部变成4×4的全白像素。通过这个规律,不难理解前面代码tex3D的采样坐标z的写法为alpha*0.9375。alpha表示透明度,0为完全透明1为完全不透明,而0.9375实际上就是15/16。这就是说在0的情况下采样的3D纹理是纯黑像素,会被clip掉,不会产生阴影;而1的情况下采样的3D纹理是全白像素,会完全产生阴影,就仿佛跟不透明物体一样。

最后再看一下这个vpos*0.25是干啥的。vpos表示的是pixel在screen space下的坐标,x和y取值范围类似[0, screenWidth],[0, screenHeight]。乘以0.25的系数就是对取值范围进行缩放处理,换言之就是将_DitherMaskLOD纹理进行放大,使其更明显。可以看下不同缩放比例的效果对比:

scale=1

scale=0.25

scale=0.0025

最后提一点的是,由于半透明的物体,render queue设置为transparent,所以在平行光绘制阴影前的depth pass阶段,是不会把半透明物体的深度信息写入depth buffer的,不过在shadow caster阶段,半透明阴影的信息还是正常绘制到shadowmap中的。这些都可以从frame debug中看出来:

Unity中的半透明阴影第7张

如果你觉得我的文章有帮助,欢迎关注我的微信公众号(大龄社畜的游戏开发之路-

Unity中的半透明阴影第8张

免责声明:文章转载自《Unity中的半透明阴影》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【App性能监控】:Android studio环境的搭建(以及遇到个各种坑)linux 命令收集 阿里云nginx升级等 查看磁盘空间 版本等下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Unity进阶之ET网络游戏开发框架 02-ET的客户端启动流程分析

版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top 优梦创客的游戏讲堂:https://91make.ke.qq.com 『优梦创客』的微信公众号:umaketop 您可以自由转载,但必须加入完整的版权声明...

(转)Unity内建图标列表

用法 Gizmos.DrawIcon(transform.position, "PointLight Gizmo"); UnityEditor.EditorGUIUtility.FindTexture("PointLight Gizmo"); Unity Editor Built-in Icons Icons what can load usingE...

基于Unity的AR开发初探:发布AR应用到Android平台

本文接上一篇,介绍一下如何通过Unity发布第一个AR应用至Android平台,在Android手机上使用我们的第一个AR应用。 一、一些准备工作 1.1 准备Java JDK 这里选择的是JDK 1.8.x版本,可以从这里下载。 1.2 准备Android SDK 这里选择的是R24.1.x-Windows版本,可以从这里下载。 Note:为了减少配置的...

Unity输入法相关(IME)

  在UI上的InputField中, 中文输入法的备选框不会跟随在光标旁边, 造成输入不方便.   看到有一个相似的, 可是是WebGL的 : https://blog.csdn.net/Rowley123456/article/details/103726927/   它通过添加Html的Input控件的方式来修改备选框位置, 直接跟平台相关了, 不具...

Unity3d:UI面板管理整合进ToLua

本文基于 https://github.com/chiuan/TTUIFramework https://github.com/jarjin/LuaFramework_UGUI 进行的二次开发,Thanks! 需求: 1.需要一个UI面板管理器,逻辑写在lua里面,方便热更新。 2.管理器控制面板的打开(show),隐藏(Hide),销毁(Destroy)...

Unity琐碎(3) UGUI 图文混排解决方案和优化

感觉使用Unity之后总能看到各种各样解决混排的方案,只能说明Unity不够体恤下情啊。这篇文章主要讲一下个人在使用过程中方案选择和优化过程,已做记录。顺便提下,开源很多意味着坑,还是要开实际需求。 1. 方案选择 1 TextMeshPro Unity 最近公布收购了TextMeshPro并且免费开源给大家使用,估计还需要几个小版本才会完全融合到Unit...