Unity Shader 简单地挖一个洞
11月就要过去了,2020年已经走到尾声。从月中开始就苦苦思考有什么值得写的东西,结果发现这个月没有写什么太值得深纠的东西,就一直拖到了现在。
效果描述
其大致效果是在地上挖一个洞,然后有东西从洞里面升起来,具体参考如下:
关键点在于营造出地上真的挖了一个坑的效果。
想法一:抠洞
那就真的在地上挖一个洞,即在地面的Shader 中添加一个额外的Clip或者功能,然后在释放技能的时候用代码传进来一个世界坐标,此时可以用世界坐标对地面进行裁剪或者透明处理。
我这里做了一个最简单Clip的方式的挖洞,可以延申成采图进行Clip 或者透明,以下是代码:
Shader "MyShader/PalneWorld"
{Properties{_MainTex ("Texture", 2D) = "white" {}_GetPos ("Start Pos(XYZ)",Vector)=(0,0,0,1)_Radius ("Radius", Float) = 0.5[Toggle]_Factor ("Factor", Int) = 1}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float3 worldPos:TEXCOORD1;};sampler2D _MainTex;float4 _MainTex_ST;float3 _GetPos;float _Radius;int _Factor;v2f vert(appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.worldPos= mul(unity_ObjectToWorld,v.vertex).xyz;return o;}fixed4 frag(v2f i) : SV_Target{float dist=distance(i.worldPos,_GetPos);clip(dist-_Radius*_Factor);fixed4 col = tex2D(_MainTex, i.uv);return col;}ENDCG}}
}
效果:
但是这个思路牵扯到的地方太多,而且要改的地方比较多,就给放弃了。
想法二:模板测试
在不抠洞的前提下,这里主要是想解决中间物体穿过地面时候的穿插问题,这个问题相当头疼,唯一的办法是让穿透的物体永远通过深度测试,但是又引发一系列问题,最后不得已引入模板测试,这是最复杂的方式了。
这里将会分成三个部分:
地板上的洞
这一部分分只是个平面,只是为了遮住地板,如图:
看起来确实像是挖了一个洞,Shader如下:
Shader "MyShader/EffectPalne2"
{Properties{_Scale("Main Texture Scale", Float) = 1 [NoScaleOffset]_MainTex ("Main Texture", 2D) = "white" {}_NoiseTex ("Distort Texture", 2D) = "white" {}_Strength ("Distort Strength", Range(-1,1)) = 0.5_SpeedX ("Speed X", Float) = 1_SpeedY ("Speed Y", Float) = 1_Radius ("Radius", Float) = 0.5}SubShader{Tags {"RenderType" = "Opaque"}LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float4 screenPos:TEXCOORD1;};sampler2D _MainTex;sampler2D _NoiseTex;half4 _NoiseTex_ST;half _Scale,_SpeedX,_SpeedY,_Strength;float _Radius;v2f vert(appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _NoiseTex);o.screenPos=ComputeScreenPos(o.vertex);return o;}fixed4 frag(v2f i) : SV_Target{float dist=distance(i.uv,0.5);clip(_Radius-dist);half t=_Time.x;// sample the texturehalf2 scrUV=_Scale*i.screenPos.xy/i.screenPos.w;//scrUV+=noise;scrUV+=half2(_SpeedX,_SpeedY)*t;half2 noiseUV=scrUV*_NoiseTex_ST.xy+_NoiseTex_ST.zw;half2 noise=tex2D(_NoiseTex,noiseUV).rg*_Strength;scrUV+=noise;fixed4 col = tex2D(_MainTex,scrUV);return col;}ENDCG}}
}
接下来是要考虑中间穿过的物体,因为正常来说,当物体和平面会被遮挡掉,如图:
所以,我把球的ZTest 设置成Always:
但是这又会造成球体会永远显示,造成遮挡不正确:
最后想到一个办法,使用模板测试,将球的显示区域控制在一个范围内,出了这个区域球就不显示,并且这个区域要和底下的坑的区域一致,我这里用的是是一个半球:
球(穿过物体的)Shader:
Shader "MyShader/Inside"
{Properties{_MainTex ("Texture", 2D) = "white" {}}SubShader{Tags { "RenderType"="Opaque" }LOD 100Stencil{Ref 1Comp Equal}ZWrite OffZTest AlwaysPass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;v2f vert(appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag(v2f i) : SV_Target{// sample the texturefixed4 col = tex2D(_MainTex, i.uv);return col;}ENDCG}}
}
半球(遮罩物体,这里需要使用GrabPass)的Shader:
Shader "MyShader/Occlusion"
{Properties{_MainTex ("Texture", 2D) = "white" {}}SubShader{Tags {"RenderType" = "Transparent" "Queue"="Transparent" "DisableBatching" = "True"}LOD 100Cull OffStencil{Ref 1Comp AlwaysPass Replace}GrabPass{"_ScreenTex"}Pass{Blend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float4 grabPos:TEXCOORD1;};sampler2D _MainTex;sampler2D _ScreenTex;float4 _MainTex_ST;v2f vert(appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.grabPos=ComputeGrabScreenPos(o.vertex);return o;}fixed4 frag(v2f i) : SV_Target{// sample the texturefixed4 col = tex2Dproj(_ScreenTex,i.grabPos);//col.rgb=1-col.rgb;return col;}ENDCG}}
}
这里还需要注意的是遮罩的序列要要小于中间物体,好让遮罩先写入模板缓冲,比如:
但是即使这样,依旧有很大的瑕疵(包括穿插以及镜头拉近的问题),但是我之前通过一些更复杂的手法把这些瑕疵都解决了,结果今天调了一天也没调好,放弃了,今天的重点也不在它。
想法三:渲染顺序
这个法不是我自己想的,但是真的很妙,缺点就是不能使用透明,因为都是在Geometry里进行的——取决于地面所在的序列,想要透明也行那就是地面也要在透明序列里,这种情况还是少…实现的效果和第一个差不多,只是不用改动地面的Shader。
这里我简单说一下思路,分别是地面,穿过的物体,挖洞的片片,还有底下要显示的东西,他们的序列是地面(比如是2000) > 挖洞的片片(1999)> 穿过的物体可以和底下要显示的东西一个层级(1998),这样就会出现一个穿透的效果,可以使用Offset -1,-1解决Z-Fighting问题,代码不是主要,主要是渲染序列的问题,就不贴代码了,可以看一下这个链接GroundCrack DepthMaskShader Tutorial(需要翻墙)。
好了,大概就是这么多了,28号写的,30号才写完,明天就12月啦。
Unity Shader 简单地挖一个洞相关推荐
- Unity Shader - 实现简单水体 - 浅水到深水颜色控制
文章目录 制作步骤 准备好水体网格 扰动水体网格 添加水体网格色调,纹理 放置海上放哨点(一些随便放的立方体) 添加水的深浅透视效果 添加水光效 重构水顶点法线 正交的相机的深度需要注意 改进 Pro ...
- Unity Shader - Noise 噪点图 - 实现简单山脉
学习记录一下噪点应用 噪点相关知识,可以看文章最下面的:References 后面有基于这篇文章重构过:Unity Shader - 简单山脉 - 顶点着色器重构法线 运行效果 噪点图 可以写了个C# ...
- 学习Shader Unity Shader 基础
1.如何充分利用 Unity Shader 来为我们的游戏增光添彩? 材质和 Unity Shader: 在Unity中,我们需要配合使用材质(Material)和 Unity Shader 才能达到 ...
- Unity3D学习笔记3——Unity Shader的初步使用
文章目录 1. 概述 2. 详论 2.1. 创建材质 2.2. 着色器 2.2.1. 名称 2.2.2. 属性 2.2.3. SubShader 2.2.3.1. 标签(Tags) 2.2.3.2. ...
- unity shader学习---光照模型(二)
更复杂的光照 效果图 理论 unity的光源类型 unity的渲染路径 在这里插入图片描述 实验 多光源 阴影 不透明物体的阴影 让物体接收阴影 统-管理光照衰减和阴影 透明度物体的阴影 代码 多光源 ...
- Unity Shader入门精要第3 章 Unity Shader 基础
Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.Unity Shader 概述 二.使用步骤 1.3.1.2 Unity 中的材质 2.Unity 中的Shader 3.Unity ...
- Unity Shader知识点(二)写一个基础漫反射Shader
前言 我们刚学习Shader时,往往会被计算机图形学相关复杂的数学.物理知识所困扰,并在学习过程中丧失兴趣.个人以为,在代码以外,学习Shader应当有本科线性代数课程基础的概念框架,在这一基础上,完 ...
- Unity Shader 实现简单的压扁效果
有点累啊,一个CoverMap搞了一周多,还是太嫩了,还有好多东西等着我去学呢,今天就写个简单的东西吧--一个把模型压扁的效果,参考博客Unity Shader - 一些玩具Shader.话不多说,先 ...
- Unity Shader 之 简单实现折叠平面(翻书)的效果
Unity Shader 之 简单实现折叠平面(翻书)的效果 目录 Unity Shader 之 简单实现折叠平面(翻书)的效果 一.简单介绍 二.实现原理 三.注意事项 四.效果预览 五.实现步骤 ...
最新文章
- 写给自己的web开发资源
- 联邦学习的隐忧:来自梯度的深度泄露
- MySqli 连接失败 MySQL connection not working: 2002 No such file or directory
- JavaScript原型彻底理解2---继承中的原型链
- 复旦计算机考研19年录取线,2019年复旦大学考研复试分数线已公布
- Sharepoint2013商务智能学习笔记之Secure Store Service服务配置(二)
- 服务器操作系统用什么好,服务器操作系统一般用什么
- PMP考试必看的答题技巧分享
- arcgis js 地图打印_Arcgis在国土空间规划编制中的应用
- 工业控制系统的体系架构
- 动手学深度学习(六、卷积神经网络)
- 树莓派调节显示屏分辨率
- Nginx:配置 proxy_pass 代理转发
- SQL优化13连问,收藏好!
- 聚观早报 | ChatGPT 停止 Plus 付费;李子柒油管广告收益登顶热搜
- oracle+故障切换,CRS故障切换异常
- ListView动态刷新某项Item
- Java九十条经验法则之第三条:用私有构造器或者枚举类型强化Singlen对象
- 京东数科“四位一体”布阵新基建沙场
- 便签数据怎么恢复 有能恢复手机便签数据的方法吗
热门文章
- 万字长文带你玩转2020全国大学生计算机技能应用大赛—C语言模考整理解析
- 把手机摄像头或智能电视摄像头数据推送到另一台手机或智能电视上的方法
- 【剑指Offer】个人学习笔记_41_数据流中的中位数
- 工业物联网的价值有哪些
- 米的换算单位和公式_Excel 怎样进行单位换算,excle怎么把米换算公里
- No valid Maven installation found.
- OpenStack社区周报:Neutron网络之负载均衡,设计OpenStack云时需要避开的十个误区...
- 云数据库ClickHouse资源隔离 - 弹性资源队列
- 主板上的北桥芯片和南桥芯片的作用和区别详解
- 用日记APP来记录生活,再也不用担心无法坚持写日记