短视频系统,实现界面阴影效果
为了便于实现,方便理解实现逻辑,本案例在Lambert光照模型(逐像素光照渲染)基础上进行改进。
原代码
1 | <br>Shader "Chapter6/LambertFrag" <br>{<br> Properties<br> {<br> _MainCol ( "Main Color" , Color) = ( 1 , 1 , 1 , 1 )<br> }<br> SubShader<br> {<br> Pass<br> {<br> CGPROGRAM<br> #pragma vertex vert<br> #pragma fragment frag<br> #include "UnityCG.cginc" <br> #include "UnityLightingCommon.cginc" <br> struct v2f<br> {<br> float4 pos : SV_POSITION;<br> float3 normal : TEXCOORD0; //这里不能是NORMAL,会跟appdata_base冲突<br> float4 vertex : TEXCOORD1;<br> };<br> fixed4 _MainCol;<br> v2f vert (appdata_base v)<br> {<br> v2f o;<br> o.pos = UnityObjectToClipPos(v.vertex);<br> o.normal = v.normal;<br> o.vertex = v.vertex;<br> return o;<br> }<br> fixed4 frag (v2f i) : SV_Target<br> {<br> //法线向量<br> float3 n = UnityObjectToWorldNormal(i.normal);<br> //n = normalize(n);<br> //灯光方向向量<br> fixed3 l = normalize(_WorldSpaceLightPos0.xyz);<br> //计算漫反射<br> fixed ndotl = dot(n,l);<br> fixed4 color = _LightColor0 * _MainCol *saturate(ndotl);<br> return color;<br> }<br> ENDCG<br> }<br> }<br>} |
附上代码:
1 | <br>Shader "Chapter6/LambertFrag" <br>{<br> Properties<br> {<br> _MainColor ( "Main Color" , Color) = ( 1 , 1 , 1 , 1 )<br> }<br> SubShader<br> {<br> Pass<br> {<br> Tags { "LightMode" = "ForwardBase" } //第一步:添加标签,计算主要灯光模式<br> CGPROGRAM<br> #pragma vertex vert<br> #pragma fragment frag<br> //第二步:调用多重编译指令,为当前pass中渲染的每个灯光编译出不同变体<br> #pragma multi_compile_fwdbase<br> #include "UnityCG.cginc"<br> //第三步:引入相关文件,便于使用内置变量和预定义函数<br> #include "Lighting.cginc"<br> #include "AutoLight.cginc"<br> struct v2f<br> {<br> float4 pos : SV_POSITION;<br> float3 normal : TEXCOORD0;//这里不能是NORMAL,会跟appdata_base冲突<br> float4 vertex: TEXCOORD1;<br> SHADOW_COORDS(2)//第四步:使用预定义宏保存阴影贴图坐标,2表示texcoord后的序号,前面两套已经被使用了<br> };<br> fixed4 _MainColor;<br> v2f vert (appdata_base v)<br> {<br> v2f o;<br> o.pos = UnityObjectToClipPos(v.vertex);<br> o.normal = v.normal;<br> o.vertex = v.vertex;<br> //第五步:TRANSFER_SHADOW<br> //1:如果当前平台可以使用屏幕空间的阴影映射技术(SCREENSPACE_SHADOWS),则会调用内置的ComputeScreenPos函数计算屏幕空间的uv坐标,存储在_ShadowCoord,后续直接用屏幕uv坐标采样屏幕阴影贴图;<br> //2:如果不支持则会使用传统的阴影映射技术,TRANSFER_SHADOW会把顶点坐标从模型空间转换到光源空间后存储到_ShadowCoord中,后续根据坐标信息对ShadowMap采样。<br> TRANSFER_SHADOW(o)<br> //我的理解是,如果使用屏幕空间的阴影映射技术,会计算物体在光照下阴影对应的屏幕空间的uv坐标<br> return o;<br> }<br> fixed4 frag (v2f i) : SV_Target<br> {<br> //法线向量<br> float3 n = UnityObjectToWorldNormal(i.normal);<br> //n = normalize(n);<br> //灯光方向向量<br> //fixed3 l = normalize(_WorldSpaceLightPos0.xyz);//意思是第一个平行光的方向<br> float3 l = WorldSpaceLightDir(i.vertex);//第六步:会根据不同类型的灯光计算灯光方向,没有归一化<br> l = normalize(l);<br> float4 worldPos = mul(unity_ObjectToWorld,i.vertex);//第七步:获取世界空间顶点坐标<br> //计算漫反射Lambert光照<br> fixed ndotl = dot(n,l);<br> fixed4 color = _LightColor0 * _MainColor *saturate(ndotl);<br> //第八步:加上4个点光源的光照<br> //Shade4PointLights: 从4个点光源计算漫反射照明,并以特殊方式打包数据。<br> //unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0,4个坐标的向量数据<br> color.rgb += Shade4PointLights(<br> unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0,<br> unity_LightColor[0].rgb,unity_LightColor[1].rgb,<br> unity_LightColor[2].rgb,unity_LightColor[3].rgb,<br> unity_4LightAtten0,worldPos.rgb,n) * _MainColor;<br> //第九步:加上环境光照<br> color += unity_AmbientSky;<br> //第十步:使用宏定义计算阴影系数<br> //用于计算光照衰减系数。参数一为返回值(光照衰减系数),参数二用于阴影计算,参数三是世界坐标<br> UNITY_LIGHT_ATTENUATION(shadowmask,i,worldPos.rgb)<br> //第十一步:阴影合成<br> color.rgb *= shadowmask;<br> return color;<br> }<br> ENDCG<br> }<br> }<br> FallBack "Diffuse"//第十二步:这里的Fallback并不是备胎,而是必要的保存投影的方式 https://blog.csdn.net/shenmifangke/article/details/50466798<br>} |
以上就是短视频系统,实现界面阴影效果, 更多内容欢迎关注之后的文章
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现